1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package com.sun.star.filter.config.tools.merge;
24 
25 //_______________________________________________
26 
27 import java.lang.*;
28 import java.util.*;
29 import java.io.*;
30 import com.sun.star.filter.config.tools.utils.*;
31 
32 //_______________________________________________
33 
34 /** can merge different xml fragments together.
35  *
36  *
37  */
38 public class Merger
39 {
40     //___________________________________________
41     // const
42 
43     private static final java.lang.String PROP_XMLVERSION      = "xmlversion"               ; // <= global cfg file
44     private static final java.lang.String PROP_XMLENCODING     = "xmlencoding"              ; // <= global cfg file
45     private static final java.lang.String PROP_XMLPATH         = "xmlpath"                  ; // <= global cfg file
46     private static final java.lang.String PROP_XMLPACKAGE      = "xmlpackage"               ; // <= global cfg file
47 
48     private static final java.lang.String PROP_SETNAME_TYPES    = "setname_types"           ; // <= global cfg file
49     private static final java.lang.String PROP_SETNAME_FILTERS  = "setname_filters"         ; // <= global cfg file
50     private static final java.lang.String PROP_SETNAME_LOADERS  = "setname_frameloaders"    ; // <= global cfg file
51     private static final java.lang.String PROP_SETNAME_HANDLERS = "setname_contenthandlers" ; // <= global cfg file
52 
53     private static final java.lang.String PROP_SUBDIR_TYPES    = "subdir_types"             ; // <= global cfg file
54     private static final java.lang.String PROP_SUBDIR_FILTERS  = "subdir_filters"           ; // <= global cfg file
55     private static final java.lang.String PROP_SUBDIR_LOADERS  = "subdir_frameloaders"      ; // <= global cfg file
56     private static final java.lang.String PROP_SUBDIR_HANDLERS = "subdir_contenthandlers"   ; // <= global cfg file
57 
58     private static final java.lang.String PROP_EXTENSION_XCU   = "extension_xcu"            ; // <= global cfg file
59     private static final java.lang.String PROP_EXTENSION_PKG   = "extension_pkg"            ; // <= global cfg file
60 
61     private static final java.lang.String PROP_DELIMITER       = "delimiter"                ; // <= global cfg file
62     private static final java.lang.String PROP_TRIM            = "trim"                     ; // <= global cfg file
63     private static final java.lang.String PROP_DECODE          = "decode"                   ; // <= global cfg file
64 
65     private static final java.lang.String PROP_FRAGMENTSDIR    = "fragmentsdir"             ; // <= cmdline
66     private static final java.lang.String PROP_TEMPDIR         = "tempdir"                  ; // <= cmdline
67     private static final java.lang.String PROP_OUTDIR          = "outdir"                   ; // <= cmdline
68     private static final java.lang.String PROP_PKG             = "pkg"                      ; // <= cmdline
69     private static final java.lang.String PROP_DEBUG           = "debug"                    ; // <= cmdline
70 
71     private static final java.lang.String PROP_TCFG            = "tcfg"                     ; // <= cmdline
72     private static final java.lang.String PROP_FCFG            = "fcfg"                     ; // <= cmdline
73     private static final java.lang.String PROP_LCFG            = "lcfg"                     ; // <= cmdline
74     private static final java.lang.String PROP_CCFG            = "ccfg"                     ; // <= cmdline
75     private static final java.lang.String PROP_LANGUAGEPACK    = "languagepack"             ; // <= cmdline
76 
77     private static final java.lang.String PROP_ITEMS           = "items"                    ; // <= pkg cfg files!
78 
79     //___________________________________________
80     // member
81 
82     //-------------------------------------------
83     /** TODO */
84     private ConfigHelper m_aCfg;
85 
86     //-------------------------------------------
87     /** TODO */
88     private Logger m_aLog;
89 
90     //-------------------------------------------
91     /** TODO */
92     private java.io.File m_aFragmentsDir;
93 
94     //-------------------------------------------
95     /** TODO */
96     private java.io.File m_aTempDir;
97 
98     //-------------------------------------------
99     /** TODO */
100     private java.io.File m_aOutDir;
101 
102     //-------------------------------------------
103     /** TODO */
104     private java.util.Vector m_lTypes;
105     private java.util.Vector m_lFilters;
106     private java.util.Vector m_lLoaders;
107     private java.util.Vector m_lHandlers;
108 
109     //___________________________________________
110     // interface
111 
112     //-------------------------------------------
113     /** initialize a new instance of this class and
114      *  try to get all needed resources from the config module.
115      *
116      *  @param  aCfg
117      *          provides access to all values of the global
118      *          config file and to the command line.
119      *
120      *  @param  aLog
121      *          can be used to print out log informations.
122      */
Merger(ConfigHelper aCfg, Logger aLog)123     public Merger(ConfigHelper aCfg,
124                   Logger       aLog)
125         throws java.lang.Exception
126     {
127         m_aCfg = aCfg;
128         m_aLog = aLog;
129 
130         m_aFragmentsDir = new java.io.File(m_aCfg.getString(PROP_FRAGMENTSDIR));
131         m_aTempDir      = new java.io.File(m_aCfg.getString(PROP_TEMPDIR     ));
132 //        m_aOutDir       = new java.io.File(m_aCfg.getString(PROP_OUTDIR      ));
133 
134         java.lang.String sDelimiter = m_aCfg.getString(PROP_DELIMITER);
135         boolean          bTrim      = m_aCfg.getBoolean(PROP_TRIM);
136         boolean          bDecode    = m_aCfg.getBoolean(PROP_DECODE);
137 
138         try
139         {
140             ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_TCFG), null);
141             m_lTypes = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
142         }
143         catch(java.util.NoSuchElementException ex1)
144         {
145             m_lTypes = new java.util.Vector();
146             //m_aLog.setWarning("Fragment list of types is missing. Parameter \"items\" seems to be invalid.");
147         }
148 
149         try
150         {
151             ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_FCFG), null);
152             m_lFilters = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
153         }
154         catch(java.util.NoSuchElementException ex1)
155         {
156             m_lFilters = new java.util.Vector();
157             //m_aLog.setWarning("Fragment list of filters is missing. Parameter \"items\" seems to be invalid.");
158         }
159 
160         try
161         {
162             ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_LCFG), null);
163             m_lLoaders = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
164         }
165         catch(java.util.NoSuchElementException ex1)
166         {
167             m_lLoaders = new java.util.Vector();
168             //m_aLog.setWarning("Fragment list of frame loader objects is missing. Parameter \"items\" seems to be invalid.");
169         }
170 
171         try
172         {
173             ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_CCFG), null);
174             m_lHandlers = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
175         }
176         catch(java.util.NoSuchElementException ex1)
177         {
178             m_lHandlers = new java.util.Vector();
179             //m_aLog.setWarning("Fragment list of content handler objects is missing. Parameter \"items\" seems to be invalid.");
180         }
181     }
182 
183     //-------------------------------------------
184     /** TODO */
merge()185     public synchronized void merge()
186         throws java.lang.Exception
187     {
188         java.lang.StringBuffer sBuffer  = new java.lang.StringBuffer(1000000);
189         java.lang.String       sPackage = m_aCfg.getString(PROP_PKG);
190 
191         m_aLog.setGlobalInfo("create package \""+sPackage+"\" ...");
192         m_aLog.setDetailedInfo("generate package header ... ");
193 
194         sBuffer.append(
195             XMLHelper.generateHeader(
196                 m_aCfg.getString (PROP_XMLVERSION         ),
197                 m_aCfg.getString (PROP_XMLENCODING        ),
198                 m_aCfg.getString (PROP_XMLPATH            ),
199                 m_aCfg.getString (PROP_XMLPACKAGE         ),
200                 m_aCfg.getBoolean(PROP_LANGUAGEPACK, false)));
201 
202         // counts all transferred fragments
203         // Can be used later to decide, if a generated package file
204         // contains "nothing"!
205         int nItemCount = 0;
206 
207         for (int i=0; i<4; ++i)
208         {
209             java.lang.String sSetName   = null;
210             java.lang.String sSubDir    = null;
211             java.util.Vector lFragments = null;
212 
213             try
214             {
215                 switch(i)
216                 {
217                     case 0: // types
218                     {
219                         m_aLog.setDetailedInfo("generate set for types ... ");
220                         sSetName   = m_aCfg.getString(PROP_SETNAME_TYPES);
221                         sSubDir    = m_aCfg.getString(PROP_SUBDIR_TYPES );
222                         lFragments = m_lTypes;
223                     }
224                     break;
225 
226                     case 1: // filters
227                     {
228                         m_aLog.setDetailedInfo("generate set for filter ... ");
229                         sSetName   = m_aCfg.getString(PROP_SETNAME_FILTERS);
230                         sSubDir    = m_aCfg.getString(PROP_SUBDIR_FILTERS );
231                         lFragments = m_lFilters;
232                     }
233                     break;
234 
235                     case 2: // loaders
236                     {
237                         m_aLog.setDetailedInfo("generate set for frame loader ... ");
238                         sSetName   = m_aCfg.getString(PROP_SETNAME_LOADERS);
239                         sSubDir    = m_aCfg.getString(PROP_SUBDIR_LOADERS );
240                         lFragments = m_lLoaders;
241                     }
242                     break;
243 
244                     case 3: // handlers
245                     {
246                         m_aLog.setDetailedInfo("generate set for content handler ... ");
247                         sSetName   = m_aCfg.getString(PROP_SETNAME_HANDLERS);
248                         sSubDir    = m_aCfg.getString(PROP_SUBDIR_HANDLERS );
249                         lFragments = m_lHandlers;
250                     }
251                     break;
252                 }
253 
254                 nItemCount += lFragments.size();
255 
256                 getFragments(
257                     new java.io.File(m_aFragmentsDir, sSubDir),
258                     sSetName,
259                     lFragments,
260                     1,
261                     sBuffer);
262             }
263             catch(java.util.NoSuchElementException exIgnore)
264                 { continue; }
265         }
266 
267         m_aLog.setDetailedInfo("generate package footer ... ");
268         sBuffer.append(XMLHelper.generateFooter());
269 
270         // Attention!
271         // If the package seem to be empty, it make no sense to generate a corresponding
272         // xml file. We should suppress writing of this file on disk completly ...
273         if (nItemCount < 1)
274         {
275             m_aLog.setWarning("Package is empty and will not result into a xml file on disk!? Please check configuration file.");
276             return;
277         }
278         m_aLog.setGlobalInfo("package contains "+nItemCount+" items");
279 
280         java.io.File aPackage = new File(sPackage);
281         m_aLog.setGlobalInfo("write temp package \""+aPackage.getPath()); // TODO encoding must be readed from the configuration
282         FileHelper.writeEncodedBufferToFile(aPackage, "UTF-8", false, sBuffer); // check for success is done inside this method!
283     }
284 
285     //-------------------------------------------
286     /** TODO */
getFragments(java.io.File aDir , java.lang.String sSetName , java.util.Vector lFragments , int nPrettyTabs, java.lang.StringBuffer sBuffer )287     private void getFragments(java.io.File           aDir       ,
288                               java.lang.String       sSetName   ,
289                               java.util.Vector       lFragments ,
290                               int                    nPrettyTabs,
291                               java.lang.StringBuffer sBuffer    )
292         throws java.lang.Exception
293     {
294         if (lFragments.size()<1)
295         {
296             m_aLog.setWarning("List of fragments is empty!? Will be ignored ...");
297             return;
298         }
299 
300         java.util.Enumeration  pFragments = lFragments.elements();
301         java.lang.String       sExtXcu    = m_aCfg.getString(PROP_EXTENSION_XCU);
302 
303         for (int tabs=0; tabs<nPrettyTabs; ++tabs)
304             sBuffer.append("\t");
305         sBuffer.append("<node oor:name=\""+sSetName+"\">\n");
306         ++nPrettyTabs;
307 
308         // special mode for generating language packs.
309         // In such case we must live with some missing fragment files.
310         // Reason behind; Not all filters are really localized.
311         // But we dont use a different fragment list. We try to locate
312         // any fragment file in its language-pack version ...
313         boolean bHandleLanguagePacks = m_aCfg.getBoolean(PROP_LANGUAGEPACK, false);
314         boolean bDebug               = m_aCfg.getBoolean(PROP_DEBUG       , false);
315         java.lang.String sEncoding   = "UTF-8";
316         if (bDebug)
317             sEncoding = "UTF-8Special";
318 
319         while(pFragments.hasMoreElements())
320         {
321             java.lang.String sFragment = (java.lang.String)pFragments.nextElement();
322             java.io.File     aFragment = new java.io.File(aDir, sFragment+"."+sExtXcu);
323 
324             // handle simple files only and check for existence!
325             if (!aFragment.exists())
326             {
327                 if (bHandleLanguagePacks)
328                 {
329                     m_aLog.setWarning("language fragment \""+aFragment.getPath()+"\" does not exist. Will be ignored.");
330                     continue;
331                 }
332                 else
333                     throw new java.io.IOException("fragment \""+aFragment.getPath()+"\" does not exists.");
334             }
335 
336             if (!aFragment.isFile())
337             {
338                 m_aLog.setWarning("fragment \""+aFragment.getPath()+"\" seem to be not a valid file.");
339                 continue;
340             }
341 
342             // copy file content of original fragment
343             // Note: A FileNotFoundException will be thrown automatically by the
344             // used reader objects. Let it break this method too. Our calli is interested
345             // on such errors :-)
346             m_aLog.setDetailedInfo("merge fragment \""+aFragment.getPath()+"\" ...");
347             FileHelper.readEncodedBufferFromFile(aFragment, sEncoding, sBuffer);
348 
349             sBuffer.append("\n");
350         }
351 
352         --nPrettyTabs;
353         for (int tabs=0; tabs<nPrettyTabs; ++tabs)
354             sBuffer.append("\t");
355         sBuffer.append("</node>\n");
356     }
357 }
358