1   /*
2   
3    * Copyright 2003 - 2013 The eFaps Team
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   * Revision:        $Rev$
18   * Last Changed:    $Date$
19   * Last Changed By: $Author$
20   */
21  
22  package org.efaps.update.schema.program.staticsource;
23  
24  import java.io.BufferedReader;
25  import java.io.ByteArrayOutputStream;
26  import java.io.IOException;
27  import java.io.InputStreamReader;
28  import java.io.OutputStreamWriter;
29  
30  import org.efaps.admin.EFapsSystemConfiguration;
31  import org.efaps.admin.KernelSettings;
32  import org.efaps.admin.common.SystemConfiguration;
33  import org.efaps.ci.CIAdminProgram;
34  import org.efaps.ci.CIType;
35  import org.efaps.db.Checkout;
36  import org.efaps.db.Instance;
37  import org.efaps.update.schema.program.staticsource.JavaScriptCompiler.OneJavaScript;
38  import org.efaps.util.EFapsException;
39  import org.mozilla.javascript.ErrorReporter;
40  import org.mozilla.javascript.EvaluatorException;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  import com.yahoo.platform.yui.compressor.JavaScriptCompressor;
45  
46  /**
47   * Compiler for JavaScript. Compiling actually means that the JavaScripts are
48   * compressed to be smaller. e.g. removing of comments, linebreaks etc.
49   * The compression can be deactivated by setting the boolean attribute
50   * "JavaScript_deactivate_Compression"  in the
51   * kernel SystemConfiguration to "true".
52   *
53   * @author The eFaps Team
54   * @version $Id$
55   */
56  public class JavaScriptCompiler
57      extends AbstractStaticSourceCompiler<OneJavaScript>
58  {
59      /**
60       * Logger for this class.
61       */
62      private static final Logger LOG = LoggerFactory.getLogger(JavaScriptCompiler.class);
63  
64      /**
65       * {@inheritDoc}
66       */
67      @Override
68      protected String getCompiledString(final Instance _instance)
69      {
70          final StringBuilder ret = new StringBuilder();
71          final Checkout checkout = new Checkout(_instance);
72          try {
73              final SystemConfiguration kernelConfig = EFapsSystemConfiguration.get();
74              final BufferedReader in = new BufferedReader(new InputStreamReader(checkout.execute(), "UTF-8"));
75              if (JavaScriptCompiler.LOG.isDebugEnabled()) {
76                  final BufferedReader in2 = new BufferedReader(new InputStreamReader(checkout.execute(), "UTF-8"));
77                  final StringBuilder bldr = new StringBuilder();
78                  String line = "";
79                  while (line != null) {
80                      line = in2.readLine();
81                      bldr.append(line != null ? line : "").append("\n");
82                  }
83                  JavaScriptCompiler.LOG.debug(bldr.toString());
84                  in2.close();
85              }
86              if (kernelConfig.getAttributeValueAsBoolean(KernelSettings.UPDATE_DEACTIVATEJSCOMP)) {
87                  String line = "";
88                  while (line != null) {
89                      line = in.readLine();
90                      ret.append(line != null ? line : "").append("\n");
91                  }
92              } else {
93                  final JavaScriptCompressor compressor = new JavaScriptCompressor(in, new ErrorReporter() {
94  
95                      /**
96                       * @see org.mozilla.javascript.ErrorReporter#error(java.lang.String, java.lang.String,
97                       * int, java.lang.String, int)
98                       * @param _error error to be written to the log
99                       * @param _arg1 not used
100                      * @param _arg2 not used
101                      * @param _arg3 not used
102                      * @param _arg4 not used
103                      */
104                     @Override
105                     public void error(final String _error,
106                                       final String _arg1,
107                                       final int _arg2,
108                                       final String _arg3,
109                                       final int _arg4)
110                     {
111                         JavaScriptCompiler.LOG.error(_error);
112                     }
113 
114                     /**
115                      * @see org.mozilla.javascript.ErrorReporter#runtimeError(java.lang.String, java.lang.String,
116                      * int, java.lang.String, int)
117                      * @param _arg0 not used
118                      * @param _arg1 not used
119                      * @param _arg2 not used
120                      * @param _arg3 not used
121                      * @param _arg4 not used
122                      * @return null not used
123                      */
124                     @Override
125                     public EvaluatorException runtimeError(final String _arg0,
126                                                            final String _arg1,
127                                                            final int _arg2,
128                                                            final String _arg3,
129                                                            final int _arg4)
130                     {
131                         return null;
132                     }
133 
134                     /**
135                      * @see org.mozilla.javascript.ErrorReporter#warning(java.lang.String, java.lang.String,
136                      * int, java.lang.String, int)
137                      * @param _warning  warning to be shown
138                      * @param _arg1     arg1 not used
139                      * @param _arg2     arg2 not used
140                      * @param _arg3     arg3 not used
141                      * @param _arg4     arg4 not used
142                      */
143                     @Override
144                     public void warning(final String _warning,
145                                         final String _arg1,
146                                         final int _arg2,
147                                         final String _arg3,
148                                         final int _arg4)
149                     {
150                         // Admin_Program_JavaScriptCompiled_Warn: do we want
151                         // warnings?
152                         try {
153                             final SystemConfiguration kernelConfig = EFapsSystemConfiguration.get();
154                             if (kernelConfig.getAttributeValueAsBoolean(KernelSettings.UPDATE_ACTIVATEJSCOMPWAR)) {
155                                 JavaScriptCompiler.LOG.warn(_warning);
156                             }
157                         } catch (final EFapsException e) {
158                             JavaScriptCompiler.LOG.error("error during checkout of Instance:" + _instance, e);
159                         }
160                     }
161                 });
162 
163                 in.close();
164                 checkout.close();
165                 final ByteArrayOutputStream byteout = new ByteArrayOutputStream();
166                 final OutputStreamWriter out = new OutputStreamWriter(byteout, "UTF-8");
167 
168                 compressor.compress(out, 140, false, true, true, true);
169                 out.flush();
170                 ret.append(byteout.toString("UTF-8"));
171             }
172         } catch (final EFapsException e) {
173             JavaScriptCompiler.LOG.error("error during checkout of Instance:" + _instance, e);
174             e.printStackTrace();
175         } catch (final EvaluatorException e) {
176             JavaScriptCompiler.LOG.error("error during the evaluation of the JavaScript of "
177                             + "Instance:" + _instance, e);
178         } catch (final IOException e) {
179             JavaScriptCompiler.LOG.error("error during reqding of the Inputstram of Instance:" + _instance, e);
180         }
181         ret.append("\n");
182         if (JavaScriptCompiler.LOG.isDebugEnabled()) {
183             JavaScriptCompiler.LOG.debug(ret.toString());
184         }
185         return ret.toString();
186     }
187 
188     /**
189      * {@inheritDoc}
190      */
191     @Override
192     public OneJavaScript getNewSource(final String _name,
193                                       final Instance _instance)
194     {
195         return new OneJavaScript(_name, _instance);
196     }
197 
198     /**
199      * {@inheritDoc}
200      */
201     @Override
202     protected CIType getClassName4Type()
203     {
204         return CIAdminProgram.JavaScript;
205     }
206 
207     /**
208      * {@inheritDoc}
209      */
210     @Override
211     protected CIType getClassName4Type2Type()
212     {
213         return  CIAdminProgram.JavaScript2JavaScript;
214     }
215 
216     /**
217      * {@inheritDoc}
218      */
219     @Override
220     protected CIType getClassName4TypeCompiled()
221     {
222         return  CIAdminProgram.JavaScriptCompiled;
223     }
224 
225     /**
226      * Class to store a javascript during compelation.
227      */
228     public static class OneJavaScript
229         extends AbstractStaticSourceCompiler.AbstractSource
230     {
231         /**
232          * @param _name     Name of the JavaScript
233          * @param _instance Instance of the JavaScript
234          */
235         public OneJavaScript(final String _name,
236                              final Instance _instance)
237         {
238             super(_name, _instance);
239         }
240     }
241 }