Source Code Cross Referenced for ImportIssues.java in  » Issue-Tracking » scarab-0.21 » org » tigris » scarab » util » xmlissues » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Issue Tracking » scarab 0.21 » org.tigris.scarab.util.xmlissues 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.tigris.scarab.util.xmlissues;
002:
003:        /* ================================================================
004:         * Copyright (c) 2000-2002 CollabNet.  All rights reserved.
005:         * 
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions are
008:         * met:
009:         * 
010:         * 1. Redistributions of source code must retain the above copyright
011:         * notice, this list of conditions and the following disclaimer.
012:         * 
013:         * 2. Redistributions in binary form must reproduce the above copyright
014:         * notice, this list of conditions and the following disclaimer in the
015:         * documentation and/or other materials provided with the distribution.
016:         * 
017:         * 3. The end-user documentation included with the redistribution, if
018:         * any, must include the following acknowlegement: "This product includes
019:         * software developed by Collab.Net <http://www.Collab.Net/>."
020:         * Alternately, this acknowlegement may appear in the software itself, if
021:         * and wherever such third-party acknowlegements normally appear.
022:         * 
023:         * 4. The hosted project names must not be used to endorse or promote
024:         * products derived from this software without prior written
025:         * permission. For written permission, please contact info@collab.net.
026:         * 
027:         * 5. Products derived from this software may not use the "Tigris" or 
028:         * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without 
029:         * prior written permission of Collab.Net.
030:         * 
031:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033:         * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034:         * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041:         * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042:         *
043:         * ====================================================================
044:         * 
045:         * This software consists of voluntary contributions made by many
046:         * individuals on behalf of Collab.Net.
047:         */
048:
049:        import java.beans.BeanDescriptor;
050:        import java.beans.IntrospectionException;
051:        import java.io.BufferedInputStream;
052:        import java.io.BufferedReader;
053:        import java.io.File;
054:        import java.io.FileInputStream;
055:        import java.io.FileReader;
056:        import java.io.IOException;
057:        import java.io.InputStream;
058:        import java.io.InputStreamReader;
059:        import java.io.Reader;
060:        import java.io.StringReader;
061:        import java.io.StringWriter;
062:        import java.io.Writer;
063:        import java.net.MalformedURLException;
064:        import java.util.Collection;
065:        import java.util.Hashtable;
066:        import java.util.Iterator;
067:        import java.util.Locale;
068:        import java.util.Map;
069:
070:        import javax.xml.parsers.ParserConfigurationException;
071:        import javax.xml.transform.OutputKeys;
072:        import javax.xml.transform.Result;
073:        import javax.xml.transform.Source;
074:        import javax.xml.transform.Transformer;
075:        import javax.xml.transform.TransformerException;
076:        import javax.xml.transform.TransformerFactory;
077:        import javax.xml.transform.URIResolver;
078:        import javax.xml.transform.dom.DOMSource;
079:        import javax.xml.transform.stream.StreamResult;
080:        import javax.xml.transform.stream.StreamSource;
081:
082:        import org.apache.commons.betwixt.XMLIntrospector;
083:        import org.apache.commons.betwixt.io.BeanReader;
084:        import org.apache.commons.betwixt.io.BeanWriter;
085:        import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
086:        import org.apache.commons.betwixt.strategy.NameMapper;
087:        import org.apache.commons.digester.Digester;
088:        import org.apache.commons.digester.Rule;
089:        import org.apache.commons.fileupload.FileItem;
090:        import org.apache.commons.logging.Log;
091:        import org.apache.commons.logging.LogFactory;
092:        import org.apache.fulcrum.localization.Localization;
093:        import org.apache.torque.TorqueException;
094:        import org.jdom.Document;
095:        import org.jdom.Element;
096:        import org.jdom.JDOMException;
097:        import org.jdom.input.SAXBuilder;
098:        import org.jdom.transform.JDOMSource;
099:        import org.tigris.scarab.om.Module;
100:        import org.tigris.scarab.om.ScarabUser;
101:        import org.tigris.scarab.om.ScarabUserManager;
102:        import org.tigris.scarab.tools.localization.L10NKeySet;
103:        import org.tigris.scarab.util.ScarabConstants;
104:        import org.tigris.scarab.util.ScarabException;
105:        import org.tigris.scarab.util.TurbineInitialization;
106:        import org.tigris.scarab.workflow.WorkflowFactory;
107:        import org.xml.sax.Attributes;
108:        import org.xml.sax.ErrorHandler;
109:        import org.xml.sax.InputSource;
110:        import org.xml.sax.SAXException;
111:        import org.xml.sax.SAXNotRecognizedException;
112:        import org.xml.sax.SAXNotSupportedException;
113:        import org.xml.sax.SAXParseException;
114:
115:        /**
116:         * This is a bean'ish object which allows one to set values for importing 
117:         * issues, and then run the actual import. 
118:         *
119:         * Amenable to the ant task wrapper or you can pass an explicit file for 
120:         * explicit import if turbine is already up and running.
121:         * 
122:         * <p>The way the ant task wrapper works is simple: call all the appropriate
123:         * set methods to define the properties. Then you will need to call the init()
124:         * and execute methods to start running things. Note: If Turbine is already
125:         * initialized, there is no need to call the init() method.</p>
126:         *
127:         * <p>Instances of this class are not thread-safe.</p>
128:         *
129:         * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
130:         * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
131:         * @version $Id: ImportIssues.java 10065 2006-04-23 21:02:14Z hair $
132:         * @since Scarab beta 14
133:         */
134:        public class ImportIssues implements  ErrorHandler {
135:            private static final Log LOG = LogFactory
136:                    .getLog(ImportIssues.class);
137:            private final transient TransformerFactory transformerFactory = TransformerFactory
138:                    .newInstance();
139:            //    private final transient DocumentBuilderFactory documentBuilderFactory 
140:            //            = DocumentBuilderFactory.newInstance();
141:
142:            private static final String JIRA_XSL = "/org/tigris/scarab/util/xmlissues/xsls/jira.xsl";
143:            private static final String BUGZILLA_XSL = "/org/tigris/scarab/util/xmlissues/xsls/bugzilla.xsl";
144:
145:            private static final ImportType SCARAB = ImportType
146:                    .valueOf("scarab");
147:            private static final ImportType BUGZILLA = ImportType
148:                    .valueOf("bugzilla");
149:            private static final ImportType JIRA = ImportType.valueOf("jira");
150:
151:            /*
152:             * The virtual URL to the document type definition (DTD) used with
153:             * this version of Scarab.  Though this file doesn't actually
154:             * exist, it's what can be used as a friendly way to refer to
155:             * Scarab's DTD in an XML file's <code>DOCTYPE</code> declaration.
156:             */
157:            public static final String SYSTEM_DTD_URI = "http://scarab.tigris.org/dtd/scarab-0.21.0.dtd";
158:
159:            /**
160:             * The absolute URL to the document type definition (DTD) used
161:             * with this version of Scarab.
162:             */
163:            private static final String INTERNAL_DTD_URI = "http://scarab.tigris.org/source/browse/*checkout*/scarab/trunk/www/dtd/scarab-0.21.0.dtd?content-type=text%2Fxml";
164:
165:            /**
166:             * The resource location of the DTD in the classpath.
167:             */
168:            private static final String DTD_RESOURCE = "/org/tigris/scarab/scarab.dtd";
169:
170:            /** 
171:             * Name of the properties file.
172:             */
173:            private String trProps = "/WEB-INF/conf/TurbineResourcesTest.properties";
174:
175:            /** 
176:             * Name of the xmlimport.properties file used for configuration of log4j.
177:             */
178:            private String configProps = "/WEB-INF/conf/xmlimport.properties";
179:
180:            private File configDir = null;
181:            private boolean sendEmail = false;
182:            private File xmlFile = null;
183:
184:            /**
185:             * Current file attachment handling code contains a security hole
186:             * which can allow a user to see any file on the host that is
187:             * readable by Scarab.  It is not easy to exploit this hole (you
188:             * have to know about file paths on a host you likely don't have
189:             * access to), and there are cases where we want to use the
190:             * functionality and can be sure the hole is not being exploited.
191:             * So adding a flag to disallow file attachments when importing
192:             * through the UI.
193:             */
194:            private boolean allowFileAttachments;
195:
196:            /**
197:             * Whether we're in validation mode, or some phase after that.
198:             */
199:            private boolean validationMode;
200:
201:            /**
202:             * A list of any errors encountered during the import, likely
203:             * added during the validation phase.
204:             */
205:            private ImportErrors importErrors;
206:
207:            public ImportIssues() {
208:                this (false);
209:            }
210:
211:            public ImportIssues(final boolean allowFileAttachments) {
212:                this .allowFileAttachments = allowFileAttachments;
213:                this .importErrors = new ImportErrors();
214:            }
215:
216:            /**
217:             * Instance of scarabissues we ran the actual insert with.
218:             *
219:             * Make it available post import so importer can get at info about
220:             * what has just been imported.
221:             */
222:            private ScarabIssues si = null;
223:
224:            public boolean getSendEmail() {
225:                return this .sendEmail;
226:            }
227:
228:            public void setSendEmail(final boolean state) {
229:                this .sendEmail = state;
230:            }
231:
232:            public File getXmlFile() {
233:                return this .xmlFile;
234:            }
235:
236:            public void setXmlFile(final File xmlFile) {
237:                this .xmlFile = xmlFile;
238:            }
239:
240:            public File getConfigDir() {
241:                return this .configDir;
242:            }
243:
244:            public void setConfigDir(final File configDir) {
245:                this .configDir = configDir;
246:            }
247:
248:            public String getConfigFile() {
249:                return this .configProps;
250:            }
251:
252:            public void setConfigFile(final String configProps) {
253:                this .configProps = configProps;
254:            }
255:
256:            public String getTurbineResources() {
257:                return this .trProps;
258:            }
259:
260:            public void setTurbineResources(final String trProps) {
261:                this .trProps = trProps;
262:            }
263:
264:            public void init() throws ScarabException, MalformedURLException,
265:                    IOException {
266:                TurbineInitialization
267:                        .setTurbineResources(getTurbineResources());
268:                TurbineInitialization.setUp(getConfigDir().getAbsolutePath(),
269:                        getConfigFile());
270:            }
271:
272:            /**
273:             * Hook method called by <a
274:             * href="http://ant.apache.org/">Ant's</a> Task wrapper.
275:             */
276:            public void execute() throws ScarabException {
277:                runImport(getXmlFile());
278:            }
279:
280:            /**
281:             * Run an import.
282:             *
283:             * Assumes we're up and running inside of turbine.
284:             *
285:             * @param importFile File to import.
286:             *
287:             * @return List of errors if any.
288:             *
289:             * @exception Exception
290:             */
291:            public Collection runImport(final File importFile)
292:                    throws ScarabException {
293:                return runImport(importFile, (Module) null);
294:            }
295:
296:            /**
297:             * Run an import.
298:             *
299:             * Assumes we're up and running inside of turbine.
300:             *
301:             * @param importFile File to import.
302:             * @param currentModule If non-null, run check that import is going 
303:             * against this module.
304:             *
305:             * @return List of errors if any.
306:             *
307:             * @exception Exception
308:             */
309:            public Collection runImport(final File importFile,
310:                    final Module currentModule) throws ScarabException {
311:                return runImport(importFile.getAbsolutePath(), importFile,
312:                        currentModule, SCARAB);
313:            }
314:
315:            /**
316:             * Run an import.
317:             *
318:             * Assumes we're up and running inside of turbine.  Awkwardly duplicates 
319:             * {@link #runImport(File) import} but duplication is so we can do the reget of
320:             * the input stream; FileInput "manages" backing up the Upload for us on the
321:             * second get of the input stream (It creates new ByteArrayInputStream 
322:             * w/ the src being a byte array of the file its kept in memory or in 
323:             * temporary storage on disk).  
324:             *
325:             * @param importFile FileItem reference to use importing.
326:             *
327:             * @return List of errors if any.
328:             *
329:             * @exception Exception
330:             */
331:            public Collection runImport(final FileItem importFile)
332:                    throws ScarabException {
333:                return runImport(importFile, (Module) null, SCARAB);
334:            }
335:
336:            /**
337:             * Run an import.
338:             *
339:             * Assumes we're up and running inside of turbine.  Awkwardly duplicates 
340:             * {@link #runImport(File) import} but duplication is so we can do the reget of
341:             * the input stream; FileInput "manages" backing up the Upload for us on the
342:             * second get of the input stream (It creates new ByteArrayInputStream 
343:             * w/ the src being a byte array of the file its kept in memory or in 
344:             * temporary storage on disk).  
345:             *
346:             * @param importFile FileItem reference to use importing.
347:             * @param currentModule If non-null, run check that import is going 
348:             * against this module.
349:             *
350:             * @return List of errors if any.
351:             *
352:             * @exception Exception
353:             */
354:            public Collection runImport(final FileItem importFile,
355:                    final Module currentModule, final ImportType type)
356:                    throws ScarabException {
357:                return runImport(importFile.getName(), importFile,
358:                        currentModule, type);
359:            }
360:
361:            /**
362:             * @param input A <code>File</code> or <code>FileItem</code>.
363:             */
364:            protected Collection runImport(final String filePath,
365:                    final Object input, final Module currentModule,
366:                    final ImportType type) throws ScarabException {
367:
368:                final String msg = "Importing issues from XML '" + filePath
369:                        + '\'';
370:                LOG.debug(msg);
371:                try {
372:                    // Disable workflow and set file attachment flag
373:                    WorkflowFactory.setForceUseDefault(true);
374:
375:                    final Reader is = getScarabFormattedReader(input, type,
376:                            currentModule);
377:
378:                    final BeanReader reader = createScarabIssuesBeanReader();
379:                    validate(filePath, is, reader, currentModule);
380:
381:                    if (importErrors == null || importErrors.isEmpty()) {
382:                        // Reget the input stream.
383:                        si = insert(filePath, getScarabFormattedReader(input,
384:                                type, currentModule), reader);
385:                    }
386:                } catch (ParserConfigurationException e) {
387:                    LOG.error(msg, e);
388:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e); //EXCEPTION
389:                } catch (TransformerException e) {
390:                    LOG.error(msg, e);
391:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e); //EXCEPTION
392:                } catch (IOException e) {
393:                    LOG.error(msg, e);
394:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e); //EXCEPTION
395:                } catch (IntrospectionException e) {
396:                    LOG.error(msg, e);
397:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e); //EXCEPTION
398:                } catch (SAXException e) {
399:                    LOG.error(msg, e);
400:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e); //EXCEPTION
401:                } catch (TorqueException e) {
402:                    LOG.error(msg, e);
403:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e); //EXCEPTION
404:                } catch (JDOMException e) {
405:                    LOG.error(msg, e);
406:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e); //EXCEPTION
407:                } catch (ScarabException e) {
408:                    LOG.error(msg, e);
409:                    throw e; //EXCEPTION
410:                } catch (ArrayIndexOutOfBoundsException e) {
411:                    LOG.error(msg, e);
412:                    throw e; //EXCEPTION
413:                } finally {
414:                    // Re-enable workflow.
415:                    WorkflowFactory.setForceUseDefault(false);
416:                }
417:
418:                return importErrors;
419:            }
420:
421:            /**
422:             * Coerces a new <code>Reader</code> from <code>input</code>.
423:             * Necessary because the stream is read twice by
424:             * <code>runImport()</code>, so the source of the stream must be
425:             * passed into that method.
426:             *
427:             * @throws IllegalArgumentException If <code>input</code> is
428:             * unrecognized.
429:             */
430:            private Reader readerFor(Object input) throws IOException {
431:                if (input instanceof  FileItem) {
432:                    return new InputStreamReader(((FileItem) input)
433:                            .getInputStream());
434:                } else if (input instanceof  File) {
435:                    return new BufferedReader(new FileReader((File) input));
436:                } else {
437:                    throw new IllegalArgumentException(); //EXCEPTION
438:                }
439:            }
440:
441:            /**
442:             * Run validation phase.  Starts by performing XML-well
443:             * formed-ness and DTD validation (if present), then checks the
444:             * content.
445:             *
446:             * @param name Filename to output in log message.  May be null.
447:             * @param is Input stream to read.
448:             * @param reader ScarabIssues bean reader instance.
449:             * @param currentModule If not <code>null</code>, check whether
450:             * import is going against this module.
451:             *
452:             * @return Any errors encountered during XML or content
453:             * validation.
454:             *
455:             * @exception Exception
456:             */
457:            protected void validate(final String name, final Reader is,
458:                    final BeanReader reader, final Module currentModule)
459:                    throws ParserConfigurationException, SAXException,
460:                    IOException {
461:                // While parsing the XML, we perform well formed-ness and DTD
462:                // validation (if present, see Xerces dynamic feature).
463:                setValidationMode(reader, true);
464:                ScarabIssues si = null;
465:                try {
466:                    si = (ScarabIssues) reader.parse(is);
467:                } catch (SAXParseException e) {
468:                    // TODO: L10N this error message from Xerces (somehow),
469:                    // and provide a prefix that describes that a XML parse
470:                    // error was encountered.
471:                    String message = new String("XML parse error at line "
472:                            + e.getLineNumber() + " column "
473:                            + e.getColumnNumber() + ": " + e.getMessage());
474:                    LOG.error(message);
475:                    importErrors.add(message);
476:                }
477:
478:                // If the XML is okay, validate the actual content.
479:                if (si != null) {
480:                    // ASSUMPTION: Parse errors prevent entry into this block.
481:                    validateContent(si, currentModule);
482:
483:                    // Log any errors encountered during import.
484:                    if (importErrors != null) {
485:                        final int nbrErrors = importErrors.size();
486:                        LOG.error("Found " + nbrErrors + " error"
487:                                + (nbrErrors == 1 ? "" : "s") + " importing '"
488:                                + name + "':");
489:                        for (Iterator itr = importErrors.iterator(); itr
490:                                .hasNext();) {
491:                            LOG.error(itr.next());
492:                        }
493:                    }
494:                }
495:            }
496:
497:            /**
498:             * Helper method for validate() which invokes validation routines
499:             * supplied by <code>ScarabIssues</code> plus (conditionally)
500:             * additional module validation.
501:             */
502:            private void validateContent(final ScarabIssues si,
503:                    final Module currentModule) {
504:                if (currentModule != null) {
505:                    // Make sure the XML module corresponds to the current
506:                    // module.  This is later than we'd like to perform this
507:                    // check, since we've already parsed the XML.  On the
508:                    // upside, si.getModule() should not return null.
509:                    final XmlModule xmlModule = si.getModule();
510:
511:                    // HELP: Check domain also?
512:
513:                    final String xmlModuleName = xmlModule.getName();
514:                    final String curModuleName = currentModule.getRealName();
515:                    if (!curModuleName.equals(xmlModuleName)) {
516:                        Object[] args = { xmlModuleName, curModuleName };
517:                        String error = Localization.format(
518:                                ScarabConstants.DEFAULT_BUNDLE_NAME,
519:                                getLocale(), "XMLAndCurrentModuleMismatch",
520:                                args);
521:                        importErrors.add(error);
522:                    }
523:
524:                    final String xmlCode = xmlModule.getCode();
525:                    if (xmlCode == null
526:                            || !currentModule.getCode().equals(xmlCode)) {
527:                        final Object[] args = { xmlCode,
528:                                currentModule.getCode() };
529:                        final String error = Localization.format(
530:                                ScarabConstants.DEFAULT_BUNDLE_NAME,
531:                                getLocale(), "XMLAndCurrentCodeMismatch", args);
532:                        importErrors.add(error);
533:                    }
534:                }
535:
536:                si.doValidateDependencies();
537:                si.doValidateUsers();
538:            }
539:
540:            /**
541:             * Do actual issue insert.
542:             *
543:             * Assumes issues passed have already been validated.  If they haven't
544:             * been, could damage scarab.
545:             *
546:             * @param name Name to use in log messages (E.g. filename).  May be null.
547:             * @param is Input stream of xml to insert.
548:             * @param reader ScarabIssues bean reader instance.
549:             * 
550:             * @return The instance of scarabissues we inserted in case you need to 
551:             * display info about the issues inserted.
552:             */
553:            protected ScarabIssues insert(final String name, final Reader is,
554:                    final BeanReader reader)
555:                    throws ParserConfigurationException, SAXException,
556:                    IOException, ScarabException {
557:                setValidationMode(reader, false);
558:                final ScarabIssues si = (ScarabIssues) reader.parse(is);
559:                si.doHandleDependencies();
560:                LOG.debug("Successfully imported " + name + '!');
561:                return si;
562:            }
563:
564:            /**
565:             * Sets the validation mode for both this instance and the
566:             * specified <code>Digester</code>.
567:             *
568:             * @param reader The XML parser to set the validation mode for.
569:             * @param state The validation mode.
570:             * @see <a href="http://xml.apache.org/xerces-j/faq-general.html#valid">Xerces validation FAQ</a>
571:             * @see <a href="http://xml.apache.org/xerces-j/features.html">Xerces SAX2 feature list</a>
572:             */
573:            private void setValidationMode(Digester reader, boolean state)
574:                    throws ParserConfigurationException, SAXException {
575:                this .validationMode = state;
576:
577:                // Setup the XML parser SAX2 features.
578:
579:                // Turn on DTD validation (these are functionally equivalent
580:                // with Xerces 1.4.4 and likely most other SAX2 impls).
581:                reader.setValidating(state);
582:                reader.setFeature("http://xml.org/sax/features/validation",
583:                        state);
584:
585:                // Validate the document only if a grammar is specified
586:                // (http://xml.org/sax/features/validation must be state).
587:                reader.setFeature(
588:                        "http://apache.org/xml/features/validation/dynamic",
589:                        state);
590:            }
591:
592:            /**
593:             * Get instance of the ScarabIssues used importing.
594:             *
595:             * You'd use this method to get at the instance of scarab issues used 
596:             * importing for case where you want to print out info on the import thats
597:             * just happened. Call after a successful import. Calling before will give
598:             * undefined results.
599:             *
600:             * @return Instance of ScarabIssues we ran the import with.
601:             */
602:            public ScarabIssues getScarabIssuesBeanReader() {
603:                return this .si;
604:            }
605:
606:            /**
607:             * A URI Resolver for use with the XSL transforms
608:             *
609:             * This resolver will map a URI in the XSL transform to an absolute
610:             * file path.
611:             */
612:            class TransformResolver implements  URIResolver {
613:
614:                File resources_path; // Absolute path to the resources
615:
616:                public TransformResolver(String resources_path) {
617:                    this .resources_path = new File(resources_path);
618:                }
619:
620:                public Source resolve(String href, String base) {
621:
622:                    File resource = new File(resources_path, href);
623:
624:                    return (resource.exists()) ? new StreamSource(resource)
625:                            : null;
626:                }
627:            }
628:
629:            /**
630:             * Return a bean reader for ScarabIssue.
631:             *
632:             * @return A bean reader.
633:             */
634:            protected BeanReader createScarabIssuesBeanReader()
635:                    throws ParserConfigurationException,
636:                    IntrospectionException, SAXNotRecognizedException,
637:                    SAXNotSupportedException {
638:                BeanReader reader = new BeanReader() {
639:                    public InputSource resolveEntity(String publicId,
640:                            String systemId) throws SAXException {
641:                        InputSource input = null;
642:                        if (publicId == null && systemId != null) {
643:                            // Resolve SYSTEM DOCTYPE.
644:                            if (SYSTEM_DTD_URI.equalsIgnoreCase(systemId)
645:                                    || INTERNAL_DTD_URI
646:                                            .equalsIgnoreCase(systemId)) {
647:                                // First look for the DTD in the classpath.
648:                                input = resolveDTDResource();
649:
650:                                if (input == null) {
651:                                    // Kick resolution back to Digester.
652:                                    input = super .resolveEntity(publicId,
653:                                            systemId);
654:                                }
655:                            }
656:                        }
657:                        return input;
658:                    }
659:
660:                    /**
661:                     * Looks for the DTD in the classpath as resouce
662:                     * {@link #DTD_RESOURCE}.
663:                     *
664:                     * @return The DTD, or <code>null</code> if not found.
665:                     */
666:                    private InputSource resolveDTDResource() {
667:                        InputStream stream = getClass().getResourceAsStream(
668:                                DTD_RESOURCE);
669:                        if (stream != null) {
670:                            LOG.debug("Located DTD in classpath using "
671:                                    + "resource path '" + DTD_RESOURCE + '\'');
672:                            return new InputSource(stream);
673:                        } else {
674:                            LOG.debug("DTD resource '" + DTD_RESOURCE
675:                                    + "' not " + "found in classpath");
676:                            return null;
677:                        }
678:                    }
679:                };
680:
681:                // Connecting Digster's logger to ours logs too verbosely.
682:                //reader.setLogger(LOG);
683:                reader.register(SYSTEM_DTD_URI, INTERNAL_DTD_URI);
684:                // Be forgiving about the encodings we accept.
685:                reader.setFeature(
686:                        "http://apache.org/xml/features/allow-java-encodings",
687:                        true);
688:                reader.setXMLIntrospector(createXMLIntrospector());
689:                reader.registerBeanClass(ScarabIssues.class);
690:                NameMapper nm = reader.getXMLIntrospector().getNameMapper();
691:                reader.addRule(nm.mapTypeToElementName(new BeanDescriptor(
692:                        ScarabIssues.class).getName()),
693:                        new ScarabIssuesSetupRule());
694:                reader.setErrorHandler(this );
695:                return reader;
696:            }
697:
698:            protected XMLIntrospector createXMLIntrospector() {
699:                XMLIntrospector introspector = new XMLIntrospector();
700:
701:                // set elements for attributes to true
702:                introspector.setAttributesForPrimitives(false);
703:
704:                // wrap collections in an XML element
705:                //introspector.setWrapCollectionsInElement(true);
706:
707:                // turn bean elements into lower case
708:                introspector.setElementNameMapper(new HyphenatedNameMapper());
709:
710:                return introspector;
711:            }
712:
713:            /**
714:             * A rule to perform setup of the a ScarabIssues instance.
715:             */
716:            class ScarabIssuesSetupRule extends Rule {
717:                public void begin(String namespace, String name,
718:                        Attributes attributes) {
719:                    ScarabIssues si = (ScarabIssues) getDigester().peek();
720:                    si.allowFileAttachments(allowFileAttachments);
721:                    si.inValidationMode(validationMode);
722:                    si.importErrors = importErrors;
723:                }
724:            }
725:
726:            /**
727:             * Method to output the bean object as XML. 
728:             * 
729:             * Not used right now.
730:             */
731:            protected void write(final Object bean, final Writer out)
732:                    throws IOException, SAXException, IntrospectionException {
733:                final BeanWriter writer = new BeanWriter(out);
734:                writer.setXMLIntrospector(createXMLIntrospector());
735:                writer.enablePrettyPrint();
736:                writer.setWriteIDs(false);
737:                writer.write(bean);
738:            }
739:
740:            private Locale getLocale() {
741:                return ScarabConstants.DEFAULT_LOCALE;
742:            }
743:
744:            // ---- org.xml.sax.ErrorHandler implementation ------------------------
745:
746:            /** Receive notification of a recoverable error. */
747:            public void error(SAXParseException e) throws SAXParseException {
748:                LOG.error("Parse Error at line " + e.getLineNumber()
749:                        + " column " + e.getColumnNumber() + ": "
750:                        + e.getMessage(), e);
751:                throw e; //EXCEPTION
752:            }
753:
754:            /** Receive notification of a non-recoverable error. */
755:            public void fatalError(SAXParseException e)
756:                    throws SAXParseException {
757:                LOG.error("Parse Fatal Error at line " + e.getLineNumber()
758:                        + " column " + e.getColumnNumber() + ": "
759:                        + e.getMessage(), e);
760:                throw e; //EXCEPTION
761:            }
762:
763:            /** Receive notification of a warning. */
764:            public void warning(SAXParseException e) {
765:                // Warnings are non-fatal.  At some point we should report
766:                // these back to the end user.
767:                LOG.debug("Parse Warning at line " + e.getLineNumber()
768:                        + " column " + e.getColumnNumber() + ": "
769:                        + e.getMessage());
770:            }
771:
772:            /** Handles transforming other xml (bugzilla or jira) formats into
773:             * the scarab xml format
774:             **/
775:            private Reader getScarabFormattedReader(final Object input,
776:                    final ImportType type, final Module currModule)
777:                    throws IOException, TransformerException, TorqueException,
778:                    JDOMException {
779:                Reader returnValue = null;
780:
781:                if (SCARAB == type) {
782:                    // is in correct format already, just return the input stream
783:                    returnValue = readerFor(input);
784:                } else if (BUGZILLA == type) {
785:                    // Location of the extensions directory for Bugzilla
786:                    // Transform configuration, mappings and attachments are here
787:                    String extensions = System.getProperty("catalina.home")
788:                            + "/../extensions/bugzilla";
789:
790:                    // Locate the Bugzilla to Scarab XSL transform
791:                    final InputStream xsl = getClass().getResourceAsStream(
792:                            BUGZILLA_XSL);
793:
794:                    // Transform Bugzilla xml to scarab format
795:                    // (Trailing '/' to resources is deliberate)
796:                    final Reader result = transformXML(new StreamSource(
797:                            readerFor(input)), xsl, currModule, extensions);
798:
799:                    // insert missing information (module)
800:                    returnValue = insertModuleNode(result, currModule);
801:                } else if (JIRA == type) {
802:                    // transform xml to scarab format
803:                    final InputStream xsl = getClass().getResourceAsStream(
804:                            JIRA_XSL);
805:                    final Reader result = transformXML(new StreamSource(
806:                            readerFor(input)), xsl, currModule, null);
807:                    // insert missing information (module)
808:                    returnValue = insertModuleNode(result, currModule);
809:                }
810:                return returnValue;
811:            }
812:
813:            private Reader transformXML(final Source xmlSource,
814:                    final InputStream xsl, final Module currModule,
815:                    final String resources) throws TransformerException {
816:                final StringWriter writer = new StringWriter();
817:                final StreamResult result = new StreamResult(writer);
818:
819:                // The resolver will help find the transform's resources
820:                if (resources != null) {
821:                    transformerFactory.setURIResolver(new TransformResolver(
822:                            resources));
823:                }
824:
825:                final Transformer transformer = (xsl != null) ? transformerFactory
826:                        .newTransformer(new StreamSource(xsl))
827:                        : transformerFactory.newTransformer();
828:
829:                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
830:
831:                // Pass this parameter to the transform to locate resources,
832:                // particularly attachments. For attachments, the
833:                // Scarab instance must be able to see this absolute path
834:                transformer.setParameter("resources_path", resources);
835:
836:                // Tell the transformer the module_code
837:                transformer.setParameter("module_code", currModule.getCode());
838:
839:                if (xsl == null) {
840:                    // plain outputting (used on a DomSource)
841:                    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
842:                    transformer.setOutputProperty(
843:                            OutputKeys.OMIT_XML_DECLARATION, "yes");
844:                }
845:                transformer.transform(xmlSource, result);
846:                System.out.println(writer.toString());
847:                return new StringReader(writer.toString());
848:            }
849:
850:            private Reader insertModuleNode(final Reader result,
851:                    final Module currModule) throws TorqueException,
852:                    JDOMException, IOException, TransformerException {
853:
854:                final ScarabUser user = ScarabUserManager
855:                        .getInstance(currModule.getOwnerId());
856:
857:                // Core Java: org.w3c.dom version (jdk1.4+ compatible)
858:                //        final DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();
859:                //        final Document doc = docBuilder.parse( new InputSource(result) );
860:                //        // insert module
861:                //        final Element root = doc.getDocumentElement();
862:                //        final Element moduleNode = doc.createElement("module");
863:                //        final Element idNode = doc.createElement("id");
864:                //        final Element parentIdNode = doc.createElement("parent-id");
865:                //        final Element nameNode = doc.createElement("name");
866:                //        final Element ownerNode = doc.createElement("owner");
867:                //        final Element descriptionNode = doc.createElement("description");
868:                //        final Element urlNode = doc.createElement("url");
869:                //        final Element domainNode = doc.createElement("domain");
870:                //        final Element codeNode = doc.createElement("code");
871:                //        
872:                //        idNode.appendChild(doc.createTextNode(String.valueOf(currModule.getModuleId())));
873:                //        parentIdNode.appendChild(doc.createTextNode(String.valueOf(currModule.getParentId())));
874:                //        nameNode.appendChild(doc.createTextNode(currModule.getName()));
875:                //        ownerNode.appendChild(doc.createTextNode(user.getUserName()));
876:                //        descriptionNode.appendChild(doc.createTextNode(currModule.getDescription()));
877:                //        urlNode.appendChild(doc.createTextNode(currModule.getUrl()));
878:                //        domainNode.appendChild(doc.createTextNode(currModule.getHttpDomain()));
879:                //        codeNode.appendChild(doc.createTextNode(currModule.getCode()));
880:                //        
881:                //        moduleNode.appendChild(idNode);
882:                //        moduleNode.appendChild(parentIdNode);
883:                //        moduleNode.appendChild(nameNode);
884:                //        moduleNode.appendChild(ownerNode);
885:                //        moduleNode.appendChild(descriptionNode);
886:                //        moduleNode.appendChild(urlNode);
887:                //        moduleNode.appendChild(domainNode);
888:                //        moduleNode.appendChild(codeNode);
889:                //        
890:                //        root.appendChild(moduleNode);
891:
892:                // JDom version (jdk1.3 compatible)
893:
894:                final SAXBuilder builder = new SAXBuilder();
895:                final Document doc = builder.build(result);
896:                final Element root = doc.getRootElement();
897:
898:                final Element moduleNode = new Element("module");
899:                final Element idNode = new Element("id");
900:                final Element parentIdNode = new Element("parent-id");
901:                final Element nameNode = new Element("name");
902:                final Element ownerNode = new Element("owner");
903:                final Element descriptionNode = new Element("description");
904:                final Element urlNode = new Element("url");
905:                final Element domainNode = new Element("domain");
906:                final Element codeNode = new Element("code");
907:
908:                idNode.setText(String.valueOf(currModule.getModuleId()));
909:                parentIdNode.setText(String.valueOf(currModule.getParentId()));
910:                nameNode.setText(currModule.getRealName());
911:                ownerNode.setText(user.getUserName());
912:                descriptionNode.setText(currModule.getDescription());
913:                urlNode.setText(currModule.getUrl());
914:                domainNode.setText(currModule.getHttpDomain());
915:                codeNode.setText(currModule.getCode());
916:
917:                moduleNode.addContent(idNode).addContent(parentIdNode)
918:                        .addContent(nameNode).addContent(ownerNode).addContent(
919:                                descriptionNode)
920:                        /*
921:                         * These are excluded for now, since your database domain may 
922:                         * not correspond to currModule.getHttpDomain().
923:                        .addContent(urlNode)
924:                        .addContent(domainNode)
925:                         */
926:                        .addContent(codeNode);
927:                root.addContent(2, moduleNode);
928:
929:                return transformXML(new JDOMSource(doc), null, currModule, null);
930:            }
931:
932:            public final static class ImportType {
933:
934:                private final String type;
935:                private static final Map instances = new Hashtable();
936:
937:                private ImportType(final String type) {
938:                    if (type == null) {
939:                        throw new IllegalArgumentException(
940:                                "Not allowed null type");
941:                    }
942:                    this .type = type;
943:                    instances.put(type, this );
944:                }
945:
946:                public static ImportType valueOf(final String type) {
947:                    ImportType instance = (ImportType) instances.get(type);
948:                    if (instance == null) {
949:                        instance = new ImportType(type);
950:                    }
951:                    return instance;
952:                }
953:            }
954:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.