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

Last change on this file since 243 was 243, checked in by patdui, 14 years ago

typo

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