source: ComponentRegistry/trunk/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/ComponentRegistryImpl.java @ 136

Last change on this file since 136 was 136, checked in by patdui, 14 years ago
  • added possibility to get an expanded CMDComponentSpec, used to get the fully expanded XSD of a profile or component.
File size: 12.3 KB
Line 
1package clarin.cmdi.componentregistry;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.FileNotFoundException;
6import java.io.FileOutputStream;
7import java.io.IOException;
8import java.io.StringWriter;
9import java.io.Writer;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.Collections;
13import java.util.HashMap;
14import java.util.Iterator;
15import java.util.List;
16import java.util.Map;
17
18import javax.xml.bind.JAXBException;
19
20import org.apache.commons.io.FileUtils;
21import org.apache.commons.io.IOUtils;
22import org.apache.commons.io.filefilter.TrueFileFilter;
23import org.apache.commons.io.filefilter.WildcardFileFilter;
24import org.apache.commons.lang.StringUtils;
25import org.slf4j.Logger;
26import org.slf4j.LoggerFactory;
27
28import clarin.cmdi.componentregistry.components.CMDComponentSpec;
29import clarin.cmdi.componentregistry.components.CMDComponentSpec.Header;
30import clarin.cmdi.componentregistry.model.AbstractDescription;
31import clarin.cmdi.componentregistry.model.ComponentDescription;
32import clarin.cmdi.componentregistry.model.ProfileDescription;
33
34public class ComponentRegistryImpl implements ComponentRegistry {
35
36    private static final String DESCRIPTION_FILE_NAME = "description.xml";
37
38    private final static Logger LOG = LoggerFactory.getLogger(ComponentRegistryImpl.class);
39
40    //bean will be injected
41    private Configuration configuration;
42
43    //cache fields
44    private Map<String, ComponentDescription> componentDescriptions;
45    private Map<String, ProfileDescription> profileDescriptions;
46    private Map<String, CMDComponentSpec> componentsCache;
47    private Map<String, CMDComponentSpec> profilesCache;
48
49    private final static ComponentRegistry INSTANCE = new ComponentRegistryImpl();
50
51    private ComponentRegistryImpl() {
52    }
53
54    public static ComponentRegistry getInstance() {
55        return INSTANCE;
56    }
57
58    public void setConfiguration(Configuration configuration) {
59        this.configuration = configuration;
60        initCache();
61    }
62
63    private void initCache() {
64        LOG.info("Initializing cache..");
65        LOG.info("CACHE: Reading and parsing all component descriptions.");
66        this.componentDescriptions = loadComponentDescriptions();
67        LOG.info("CACHE: Reading and parsing all profile descriptions.");
68        this.profileDescriptions = loadProfileDescriptions();
69        LOG.info("CACHE: Reading and parsing all components.");
70        this.componentsCache = loadComponents();
71        LOG.info("CACHE: Reading and parsing all profiles.");
72        this.profilesCache = loadProfiles();
73        LOG.info("CACHE: Loaded " + profileDescriptions.size() + " profile descriptions, " + profilesCache.size() + " profiles.");
74        LOG.info("CACHE: Loaded " + componentDescriptions.size() + " components descriptions, " + componentsCache.size() + " components.");
75        LOG.info("CACHE initialized. Any occured errors should be adressed, files could be corrupt."
76                + " Components and Profiles with errors will not be shown to users.");
77    }
78
79    private Map<String, CMDComponentSpec> loadProfiles() {
80        Map<String, CMDComponentSpec> result = new HashMap<String, CMDComponentSpec>();
81        for (Iterator<String> iter = profileDescriptions.keySet().iterator(); iter.hasNext();) {
82            String id = iter.next();
83            CMDComponentSpec spec = getUncachedProfile(id);
84            if (spec != null) {
85                result.put(id, spec);
86            } else {
87                iter.remove(); // cannot load actual profile so remove description from cache.
88            }
89        }
90        return result;
91    }
92
93    CMDComponentSpec getUncachedProfile(String id) {
94        File file = getProfileFile(id);
95        CMDComponentSpec spec = MDMarshaller.unmarshal(CMDComponentSpec.class, file);
96        return spec;
97    }
98
99    private Map<String, CMDComponentSpec> loadComponents() {
100        Map<String, CMDComponentSpec> result = new HashMap<String, CMDComponentSpec>();
101        for (Iterator<String> iter = componentDescriptions.keySet().iterator(); iter.hasNext();) {
102            String id = iter.next();
103            CMDComponentSpec spec = getUncachedComponent(id);
104            if (spec != null) {
105                result.put(id, spec);
106            } else {
107                iter.remove(); // cannot load actual component so remove description from cache.
108            }
109        }
110        return result;
111    }
112
113    CMDComponentSpec getUncachedComponent(String id) {
114        File file = getComponentFile(id);
115        CMDComponentSpec spec = MDMarshaller.unmarshal(CMDComponentSpec.class, file);
116        return spec;
117    }
118
119    private Map<String, ProfileDescription> loadProfileDescriptions() {
120        Collection files = FileUtils.listFiles(configuration.getProfileDir(), new WildcardFileFilter(DESCRIPTION_FILE_NAME),
121                TrueFileFilter.TRUE);
122        Map<String, ProfileDescription> result = new HashMap<String, ProfileDescription>();
123        for (Iterator iterator = files.iterator(); iterator.hasNext();) {
124            File file = (File) iterator.next();
125            ProfileDescription desc = MDMarshaller.unmarshal(ProfileDescription.class, file);
126            if (desc != null)
127                result.put(desc.getId(), desc);
128        }
129        return result;
130    }
131
132    private Map<String, ComponentDescription> loadComponentDescriptions() {
133        Collection files = FileUtils.listFiles(getComponentDir(), new WildcardFileFilter(DESCRIPTION_FILE_NAME), TrueFileFilter.TRUE);
134        Map<String, ComponentDescription> result = new HashMap<String, ComponentDescription>();
135        for (Iterator iterator = files.iterator(); iterator.hasNext();) {
136            File file = (File) iterator.next();
137            ComponentDescription desc = MDMarshaller.unmarshal(ComponentDescription.class, file);
138            if (desc != null)
139                result.put(desc.getId(), desc);
140        }
141        return result;
142    }
143
144    private void updateCache(CMDComponentSpec spec, AbstractDescription description) {
145        if (description.isProfile()) {
146            profileDescriptions.put(description.getId(), (ProfileDescription) description);
147            profilesCache.put(description.getId(), spec);
148        } else {
149            componentDescriptions.put(description.getId(), (ComponentDescription) description);
150            componentsCache.put(description.getId(), spec);
151        }
152    }
153
154    private File getComponentDir() {
155        return configuration.getComponentDir();
156    }
157
158    public List<ComponentDescription> getComponentDescriptions() {
159        return new ArrayList(componentDescriptions.values());
160    }
161
162    public CMDComponentSpec getMDProfile(String profileId) {
163        CMDComponentSpec result = profilesCache.get(profileId);
164        return result;
165    }
166
167    public String getMDProfileAsXml(String profileId) {
168        String result = null;
169        File file = getProfileFile(profileId);
170        try {
171            result = IOUtils.toString(new FileInputStream(file));
172        } catch (FileNotFoundException e) {
173            LOG.error("Cannot retrieve file: " + file, e);
174        } catch (IOException e) {
175            LOG.error("Cannot retrieve content from file: " + file, e);
176        }
177        return result;
178    }
179
180    public String getMDProfileAsXsd(String profileId) {
181        CMDComponentSpec expandedSpec = CMDComponentSpecExpander.expandProfile(profileId, this);
182        return getXsd(expandedSpec);
183    }
184
185    private String getXsd(CMDComponentSpec expandedSpec) {
186        Writer writer = new StringWriter();
187        MDMarshaller.generateXsd(expandedSpec, writer);
188        return writer.toString();
189    }
190
191    public File getProfileFile(String profileId) {
192        String id = stripRegistryId(profileId);
193        File file = new File(configuration.getProfileDir(), id + File.separator + id + ".xml");
194        return file;
195    }
196
197    public CMDComponentSpec getMDComponent(String componentId) {
198        CMDComponentSpec result = componentsCache.get(componentId);
199        return result;
200    }
201
202    public String getMDComponentAsXml(String componentId) {
203        String result = null;
204        File file = getComponentFile(componentId);
205        try {
206            result = IOUtils.toString(new FileInputStream(file), "UTF-8");
207        } catch (FileNotFoundException e) {
208            LOG.error("Cannot retrieve file: " + file, e);
209        } catch (IOException e) {
210            LOG.error("Cannot retrieve content from file: " + file, e);
211        }
212        return result;
213    }
214
215    public String getMDComponentAsXsd(String componentId) {
216        CMDComponentSpec expandedSpec = CMDComponentSpecExpander.expandComponent(componentId, this);
217        return getXsd(expandedSpec);
218    }
219
220    public File getComponentFile(String componentId) {
221        String id = stripRegistryId(componentId);
222        File file = new File(configuration.getComponentDir(), id + File.separator + id + ".xml");
223        return file;
224    }
225
226    private String stripRegistryId(String id) {
227        return StringUtils.removeStart(id, REGISTRY_ID);
228    }
229
230    public List<ProfileDescription> getProfileDescriptions() {
231        return new ArrayList(profileDescriptions.values());
232    }
233
234    /**
235     * CMDComponentSpec and description are assumed to be valid.
236     */
237    public int registerMDComponent(ComponentDescription description, CMDComponentSpec spec) {
238        LOG.info("Attempt to register component: " + description);
239        return register(configuration.getComponentDir(), description, spec, "component");
240    }
241
242    /**
243     * CMDComponentSpec and description are assumed to be valid.
244     */
245    public int registerMDProfile(ProfileDescription profileDescription, CMDComponentSpec spec) {
246        LOG.info("Attempt to register profile: " + profileDescription);
247        return register(configuration.getProfileDir(), profileDescription, spec, "profile");
248    }
249
250    private int register(File storageDir, AbstractDescription description, CMDComponentSpec spec, String type) {
251        String strippedId = stripRegistryId(description.getId());
252        File dir = new File(storageDir, strippedId);
253        boolean success = false;
254        try {
255            boolean dirCreated = dir.mkdir();
256            if (dirCreated) {
257                writeDescription(dir, description);
258                enrichSpecHeader(spec, description);
259                writeCMDComponentSpec(dir, strippedId + ".xml", spec);
260                success = true;
261            }
262        } catch (IOException e) {
263            LOG.error("Register failed:", e);
264        } catch (JAXBException e) {
265            LOG.error("Register failed:", e);
266        } finally {
267            if (!success) {
268                LOG.info("Registration of " + type + " " + description + " unsuccessful. Cleaning up created folders.");
269                try {
270                    FileUtils.deleteDirectory(dir);
271                } catch (IOException e) {
272                    LOG.error("Error in registration. Cleaning up " + type + " failed: " + dir + " :", e);
273                }
274                return -1;
275            }
276        }
277        LOG.info("Succesfully registered a " + type + " in " + dir + " " + type + "= " + description);
278        updateCache(spec, description);
279        return 0;
280    }
281
282    private void enrichSpecHeader(CMDComponentSpec spec, AbstractDescription description) {
283        Header header = spec.getHeader();
284        header.setID(description.getId());
285        if (StringUtils.isEmpty(header.getName())) {
286            header.setName(description.getName());
287        }
288        if (StringUtils.isEmpty(header.getDescription())) {
289            header.setDescription(description.getDescription());
290        }
291
292    }
293
294    private void writeDescription(File profileDir, AbstractDescription description) throws IOException, JAXBException {
295        File metadataFile = new File(profileDir, DESCRIPTION_FILE_NAME);
296        FileOutputStream fos = new FileOutputStream(metadataFile);
297        MDMarshaller.marshal(description, fos);
298        LOG.info("Saving metadata is successful " + metadataFile);
299    }
300
301    private void writeCMDComponentSpec(File profileDir, String profileName, CMDComponentSpec spec) throws IOException, JAXBException {
302        File file = new File(profileDir, profileName);
303        FileOutputStream fos = new FileOutputStream(file);
304        MDMarshaller.marshal(spec, fos);
305        LOG.info("Saving profile/component is successful " + file);
306    }
307
308    public List<MDProfile> searchMDProfiles(String searchPattern) {
309        return Collections.EMPTY_LIST;
310    }
311
312}
Note: See TracBrowser for help on using the repository browser.