View Javadoc

1   /*
2    * Copyright (C) 2003-2012 David E. Berry
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17   *
18   * A copy of the GNU Lesser General Public License may also be found at
19   * http://www.gnu.org/licenses/lgpl.txt
20   */
21  package org.synchronoss.cpo.meta;
22  
23  import org.apache.xmlbeans.*;
24  import org.slf4j.*;
25  import org.synchronoss.cpo.CpoException;
26  import org.synchronoss.cpo.cache.CpoMetaDescriptorCache;
27  import org.synchronoss.cpo.core.cpoCoreMeta.CpoMetaDataDocument;
28  import org.synchronoss.cpo.exporter.*;
29  import org.synchronoss.cpo.helper.*;
30  import org.synchronoss.cpo.meta.domain.*;
31  import org.synchronoss.cpo.parser.ExpressionParser;
32  
33  import java.io.*;
34  import java.lang.reflect.*;
35  import java.util.*;
36  
37  /**
38   * @author dberry
39   */
40  public class CpoMetaDescriptor extends CpoMetaDescriptorCache implements CpoMetaAdapter, CpoMetaExportable {
41  
42    private static final Logger logger = LoggerFactory.getLogger(CpoMetaDescriptor.class);
43    private String name = null;
44    private boolean caseSensitive = true;
45    private AbstractCpoMetaAdapter metaAdapter = null;
46  
47    // used by cpo util
48    private String defaultPackageName;
49  
50    private CpoMetaDescriptor() {
51    }
52  
53    protected CpoMetaDescriptor(String name, boolean caseSensitive) throws CpoException {
54      this.name = name;
55      this.caseSensitive = caseSensitive;
56  
57      // Lets create the metaAdapter
58      try {
59        Class metaAdapterClass = getMetaAdapterClass();
60        metaAdapter = (AbstractCpoMetaAdapter)metaAdapterClass.newInstance();
61        logger.debug("Created MetaAdapter: " + metaAdapterClass.getName());
62      } catch (InstantiationException ie) {
63        throw new CpoException("Could not instantiate CpoMetaAdapter: " + ExceptionHelper.getLocalizedMessage(ie));
64      } catch (IllegalAccessException iae) {
65        throw new CpoException("Could not access CpoMetaAdapter: " + ExceptionHelper.getLocalizedMessage(iae));
66      } catch (ClassCastException cce) {
67        throw new CpoException("CpoMetaAdapter must extend AbstractCpoMetaAdapter: " + getMetaAdapterClass().getName() + ":" + ExceptionHelper.getLocalizedMessage(cce));
68      }
69    }
70  
71    protected Class getMetaAdapterClass() throws CpoException {
72      throw new CpoException("getMetaAdapterClass() must be implemented");
73    }
74  
75    public static boolean isValidMetaDescriptor(CpoMetaDescriptor metaDescriptor) {
76      return (findCpoMetaDescriptor(metaDescriptor.getName()) != null);
77    }
78  
79    public static CpoMetaDescriptor getInstance(String name) throws CpoException {
80      return findCpoMetaDescriptor(name);
81    }
82  
83    public static void removeInstance(String name) throws CpoException {
84      removeCpoMetaDescriptor(name);
85    }
86  
87    public static void clearAllInstances() throws CpoException {
88      clearCpoMetaDescriptorCache();
89    }
90  
91    public static CpoMetaDescriptor getInstance(String name, String metaXml, boolean caseSensitive) throws CpoException {
92      List<String> metaXmls = new ArrayList<String>();
93      metaXmls.add(metaXml);
94      return createUpdateInstance(name, metaXmls, caseSensitive);
95    }
96  
97    public static CpoMetaDescriptor getInstance(String name, List<String> metaXmls, boolean caseSensitive) throws CpoException {
98      return createUpdateInstance(name, metaXmls, caseSensitive);
99    }
100 
101   public static CpoMetaDescriptor getInstance(String name, String[] metaXmls, boolean caseSensitive) throws CpoException {
102     return createUpdateInstance(name, metaXmls, caseSensitive);
103   }
104 
105   /**
106    * @return A collection of names of all meta descriptors currently loaded
107    */
108   public static Collection<String> getCpoMetaDescriptorNames() {
109     return CpoMetaDescriptorCache.getCpoMetaDescriptorNames();
110   }
111 
112   public static void refreshDescriptorMeta(String name, List<String> metaXmls) throws CpoException {
113     CpoMetaDescriptor metaDescriptor = findCpoMetaDescriptor(name);
114     if (metaDescriptor != null) {
115       metaDescriptor.refreshDescriptorMeta(metaXmls);
116     }
117   }
118 
119   public void refreshDescriptorMeta(List<String> metaXmls) throws CpoException {
120     createUpdateInstance(this.getName(), metaXmls, caseSensitive);
121   }
122 
123   protected static CpoMetaDescriptor createUpdateInstance(String name, List<String> metaXmls, boolean caseSensitive) throws CpoException {
124     return createUpdateInstance(name, metaXmls.toArray(new String[metaXmls.size()]), caseSensitive);
125   }
126 
127   protected static CpoMetaDescriptor createUpdateInstance(String name, String[] metaXmls, boolean caseSensitive) throws CpoException {
128     CpoMetaDescriptor metaDescriptor = findCpoMetaDescriptor(name);
129     String metaDescriptorClassName = null;
130 
131     for (String metaXml : metaXmls) {
132       InputStream is = CpoClassLoader.getResourceAsStream(metaXml);
133       if (is == null) {
134         logger.info("Resource Not Found: " + metaXml);
135         try {
136           is = new FileInputStream(metaXml);
137         } catch (FileNotFoundException fnfe) {
138           logger.info("File Not Found: " + metaXml);
139           is = null;
140         }
141       }
142       try {
143         CpoMetaDataDocument metaDataDoc;
144         if (is == null) {
145           metaDataDoc = CpoMetaDataDocument.Factory.parse(metaXml);
146         } else {
147           metaDataDoc = CpoMetaDataDocument.Factory.parse(is);
148         }
149 
150         String errMsg = XmlBeansHelper.validateXml(metaDataDoc);
151         if (errMsg != null) {
152           throw new CpoException("Invalid metaXml: " + metaXml + ":" + errMsg);
153         }
154 
155         if (metaDescriptor == null) {
156           logger.debug("Getting descriptor name");
157           metaDescriptorClassName = metaDataDoc.getCpoMetaData().getMetaDescriptor();
158           logger.debug("Getting the Class");
159           Class<?> clazz = CpoClassLoader.forName(metaDescriptorClassName);
160           logger.debug("Getting the Constructor");
161           if (clazz == null) {
162             logger.debug("clazz==null");
163           }
164           Constructor<?> cons = clazz.getConstructor(String.class, boolean.class);
165           logger.debug("Creating the instance");
166           metaDescriptor = (CpoMetaDescriptor)cons.newInstance(name, caseSensitive);
167           addCpoMetaDescriptor(metaDescriptor);
168         } else if (!metaDescriptor.getClass().getName().equals(metaDataDoc.getCpoMetaData().getMetaDescriptor())) {
169           throw new CpoException("Error processing multiple metaXml files. All files must have the same CpoMetaDescriptor class name.");
170         }
171 
172         metaDescriptor.setDefaultPackageName(metaDataDoc.getCpoMetaData().getDefaultPackageName());
173         metaDescriptor.getCpoMetaAdapter().loadCpoMetaDataDocument(metaDataDoc, caseSensitive);
174       } catch (IOException ioe) {
175         throw new CpoException("Error processing metaData from InputStream: " + metaXml + ": " + ExceptionHelper.getLocalizedMessage(ioe));
176       } catch (XmlException xe) {
177         throw new CpoException("Error processing metaData from String: " + metaXml + ": " + ExceptionHelper.getLocalizedMessage(xe));
178       } catch (ClassNotFoundException cnfe) {
179         throw new CpoException("CpoMetaAdapter not found: " + metaDescriptorClassName + ": " + ExceptionHelper.getLocalizedMessage(cnfe));
180       } catch (IllegalAccessException iae) {
181         throw new CpoException("Could not access CpoMetaAdapter: " + metaDescriptorClassName + ": " + ExceptionHelper.getLocalizedMessage(iae));
182       } catch (InstantiationException ie) {
183         throw new CpoException("Could not instantiate CpoMetaAdapter: " + metaDescriptorClassName + ": " + ExceptionHelper.getLocalizedMessage(ie));
184       } catch (InvocationTargetException ite) {
185         throw new CpoException("Could not invoke constructor: " + metaDescriptorClassName + ": " + ExceptionHelper.getLocalizedMessage(ite));
186       } catch (IllegalArgumentException iae) {
187         throw new CpoException("Illegal Argument to constructor: " + metaDescriptorClassName + ": " + ExceptionHelper.getLocalizedMessage(iae));
188       } catch (NoSuchMethodException nsme) {
189         throw new CpoException("Could not find constructor: " + metaDescriptorClassName + ": " + ExceptionHelper.getLocalizedMessage(nsme));
190       } catch (SecurityException se) {
191         throw new CpoException("Not allowed to access constructor: " + metaDescriptorClassName + ": " + ExceptionHelper.getLocalizedMessage(se));
192       } catch (ClassCastException cce) {
193         throw new CpoException("Class is not instance of CpoMetaDescriptor: " + metaDescriptorClassName + ":" + ExceptionHelper.getLocalizedMessage(cce));
194       } finally {
195         if (is != null) {
196           try {
197             is.close();
198           } catch (Exception e) {
199             if (logger.isTraceEnabled()) {
200               logger.trace(e.getLocalizedMessage());
201             }
202           }
203         }
204       }
205     }
206 
207     return metaDescriptor;
208   }
209 
210   protected static CpoMetaDescriptor createUpdateInstance(CpoMetaDescriptor metaDescriptor, CpoMetaAdapter metaAdapter) throws CpoException {
211     if (metaDescriptor != null && metaAdapter != null) {
212       addCpoMetaDescriptor(metaDescriptor);
213     }
214     return metaDescriptor;
215   }
216 
217   protected AbstractCpoMetaAdapter getCpoMetaAdapter() {
218     return metaAdapter;
219   }
220 
221   @Override
222   public <T> CpoClass getMetaClass(T obj) throws CpoException {
223     CpoClass cpoClass = getCpoMetaAdapter().getMetaClass(obj);
224     if (cpoClass != null && cpoClass.getMetaClass() == null) {
225       cpoClass.loadRunTimeInfo(this);
226     }
227 
228     return cpoClass;
229   }
230 
231   @Override
232   public List<CpoClass> getCpoClasses() throws CpoException {
233     return getCpoMetaAdapter().getCpoClasses();
234   }
235 
236   public void addCpoClass(CpoClass cpoClass) throws CpoException {
237     getCpoMetaAdapter().addCpoClass(cpoClass);
238   }
239 
240   public void removeCpoClass(CpoClass cpoClass) throws CpoException {
241     getCpoMetaAdapter().removeCpoClass(cpoClass);
242   }
243 
244   @Override
245   public ExpressionParser getExpressionParser() throws CpoException {
246     return getCpoMetaAdapter().getExpressionParser();
247   }
248 
249   @Override
250   public String getJavaTypeName(CpoAttribute attribute) throws CpoException {
251     return getCpoMetaAdapter().getJavaTypeName(attribute);
252   }
253 
254   @Override
255   public Class getJavaTypeClass(CpoAttribute attribute) throws CpoException {
256     return getCpoMetaAdapter().getJavaTypeClass(attribute);
257   }
258 
259   @Override
260   public List<String> getAllowableDataTypes() throws CpoException {
261     return getCpoMetaAdapter().getAllowableDataTypes();
262   }
263 
264   public CpoClass createCpoClass() throws CpoException {
265     return getCpoMetaAdapter().createCpoClass(caseSensitive);
266   }
267 
268   public CpoAttribute createCpoAttribute() throws CpoException {
269     return getCpoMetaAdapter().createCpoAttribute();
270   }
271 
272   public CpoFunctionGroup createCpoFunctionGroup() throws CpoException {
273     return getCpoMetaAdapter().createCpoFunctionGroup();
274   }
275 
276   public CpoFunction createCpoFunction() throws CpoException {
277     return getCpoMetaAdapter().createCpoFunction();
278   }
279 
280   public CpoArgument createCpoArgument() throws CpoException {
281     return getCpoMetaAdapter().createCpoArgument();
282   }
283 
284   public String getDefaultPackageName() {
285     return defaultPackageName;
286   }
287 
288   public void setDefaultPackageName(String packageName) {
289     if (packageName != null) {
290       defaultPackageName = packageName;
291     }
292   }
293 
294   public String getName() {
295     return name;
296   }
297 
298   protected MetaXmlObjectExporter getMetaXmlObjectExporter() {
299     return new CoreMetaXmlObjectExporter(this);
300   }
301 
302   protected final CpoMetaDataDocument export() {
303     MetaXmlObjectExporter metaXmlObjectExporter = getMetaXmlObjectExporter();
304 
305     // need these sorted
306     List<CpoClass> classList = new ArrayList<CpoClass>();
307     classList.addAll(getCpoMetaAdapter().getCpoClasses());
308     Collections.sort(classList);
309     for (CpoClass cpoClass : classList) {
310       cpoClass.acceptMetaDFVisitor(metaXmlObjectExporter);
311     }
312     return metaXmlObjectExporter.getCpoMetaDataDocument();
313   }
314 
315   public final void export(File file) throws CpoException {
316     try {
317       CpoMetaDataDocument doc = export();
318       doc.save(file, XmlBeansHelper.getXmlOptions());
319     } catch (IOException ex) {
320       throw new CpoException(ex.getMessage(), ex);
321     }
322   }
323 
324   public final void export(Writer writer) throws CpoException {
325     try {
326       CpoMetaDataDocument doc = export();
327       doc.save(writer, XmlBeansHelper.getXmlOptions());
328     } catch (IOException ex) {
329       throw new CpoException(ex.getMessage(), ex);
330     }
331   }
332 
333   public final void export(OutputStream outputStream) throws CpoException {
334     try {
335       CpoMetaDataDocument doc = export();
336       doc.save(outputStream, XmlBeansHelper.getXmlOptions());
337     } catch (IOException ex) {
338       throw new CpoException(ex.getMessage(), ex);
339     }
340   }
341 
342   public boolean isCaseSensitive() {
343     return caseSensitive;
344   }
345 }