1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package com.sun.star.script.framework.container;
29 
30 import java.net.URL;
31 
32 import java.io.ByteArrayInputStream;
33 
34 import java.util.Vector;
35 import java.util.StringTokenizer;
36 
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 
40 import com.sun.star.script.framework.log.LogUtils;
41 
42 import com.sun.star.script.framework.provider.PathUtils;
43 
44 import com.sun.star.script.framework.io.XInputStreamImpl;
45 
46 import com.sun.star.script.framework.container.ScriptEntry;
47 import com.sun.star.script.framework.container.Parcel;
48 
49 import com.sun.star.script.framework.io.UCBStreamHandler;
50 
51 import com.sun.star.ucb.XSimpleFileAccess2;
52 
53 import com.sun.star.uno.UnoRuntime;
54 
55 public class ScriptMetaData extends ScriptEntry implements Cloneable {
56     private boolean hasSource = false;
57     private String locationPlaceHolder = "";
58     private String source;
59     private Parcel parent;
60 
61 
62     public ScriptMetaData( Parcel parent, ScriptEntry entry,
63                            String source )
64     {
65         super( entry );
66         this.parent = parent;
67         if ( source != null )
68         {
69             this.hasSource = true;
70             this.source = source;
71         }
72 
73     }
74 
75     public boolean hasSource()
76     {
77         return hasSource;
78     }
79     public String getSource()
80     {
81 
82         if ( source !=null && hasSource )
83         {
84             return source;
85         }
86         else
87         {
88             return null;
89         }
90     }
91 
92     public byte[] getSourceBytes()
93     {
94         if ( source !=null && hasSource )
95         {
96             return source.getBytes();
97         }
98         else
99         {
100             return null;
101         }
102 
103     }
104     public Object clone() throws CloneNotSupportedException {
105         return super.clone();
106     }
107 
108     public boolean equals(ScriptMetaData other) {
109         if (super.equals(other) &&
110             hasSource == other.hasSource() )
111         {
112             return true;
113         }
114         return false;
115     }
116 
117     public String getScriptFullURL()
118     {
119         String url = "vnd.sun.star.script:" + parent.getName() + "." + getLanguageName() +
120             "?" + "language=" + getLanguage() +
121             "&location=" + getParcelLocation();
122          return url;
123     }
124 
125     public String getShortFormScriptURL()
126     {
127         String url = "vnd.sun.star.script:" + parent.getName() + "." + getLanguageName() +
128             "?" + "language=" + getLanguage() +
129             "&location=" + getLocationPlaceHolder();
130         return url;
131     }
132 
133     // TODO probably should be private should not be necessary
134     // to be exposed at all
135 
136 	private static final String SHARE =
137         "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" +
138         PathUtils.BOOTSTRAP_NAME +
139         "::BaseInstallation}/share";
140 
141 	private static final String USER =
142         "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" +
143         PathUtils.BOOTSTRAP_NAME +
144         "::UserInstallation}/user";
145 
146 	private static final String UNO_USER_PACKAGES1 =
147         "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE";
148 
149 	private static final String UNO_USER_PACKAGES2 =
150         USER + "/uno_packages";
151 
152 	private static final String UNO_SHARED_PACKAGES1 =
153         "$UNO_SHARED_PACKAGES_CACHE";
154 
155 	private static final String UNO_SHARED_PACKAGES2 =
156         SHARE + "/uno_packages";
157 
158     public static String getLocationPlaceHolder(String url, String pkgname)
159 	{
160         String result = "Unknown";
161 
162         if ( url.indexOf(UNO_USER_PACKAGES1) > -1 ||
163              url.indexOf(UNO_USER_PACKAGES2) > -1 )
164         {
165             result = PathUtils.make_url( "user:uno_packages", pkgname );
166         }
167         else if ( url.indexOf(UNO_SHARED_PACKAGES1) > -1 ||
168                   url.indexOf(UNO_SHARED_PACKAGES2) > -1 )
169         {
170             result = PathUtils.make_url( "share:uno_packages", pkgname );
171         }
172         else if ( url.indexOf(SHARE) == 0 )
173         {
174             result = "share";
175         }
176         else if ( url.indexOf(USER) == 0 )
177         {
178             result = "user";
179         }
180         else if ( url.indexOf("vnd.sun.star.tdoc:") == 0 )
181         {
182             result = "document";
183         }
184         return result;
185 	}
186 
187     public String getLocationPlaceHolder()
188     {
189         String placeHolder = "Unknown";
190         String pathToParcel = parent.getPathToParcel();
191 
192         if ( pathToParcel.indexOf(UNO_USER_PACKAGES1) > -1 ||
193              pathToParcel.indexOf(UNO_USER_PACKAGES2) > -1 )
194         {
195             // its a package
196             placeHolder = "user:uno_packages";
197             String unoPkg = parent.parent.getName();
198             if ( unoPkg != null )
199             {
200                 placeHolder = PathUtils.make_url( placeHolder, unoPkg );
201             }
202         }
203         else if ( pathToParcel.indexOf(UNO_SHARED_PACKAGES1) > -1 ||
204                   pathToParcel.indexOf(UNO_SHARED_PACKAGES2) > -1 )
205         {
206             //its a package
207             placeHolder = "share:uno_packages";
208             String unoPkg = parent.parent.getName();
209             if ( unoPkg != null )
210             {
211                 placeHolder = PathUtils.make_url( placeHolder, unoPkg );
212             }
213         }
214         else if ( pathToParcel.indexOf(SHARE) == 0 )
215         {
216             placeHolder = "share";
217         }
218         else if ( pathToParcel.indexOf(USER) == 0 )
219         {
220             placeHolder = "user";
221         }
222         else if ( pathToParcel.indexOf("vnd.sun.star.tdoc:") == 0 )
223         {
224             placeHolder = "document";
225         }
226         // TODO handling document packages ??? not really sure of package url
227 /*        else
228         {
229         } */
230         return placeHolder;
231     }
232 
233     // TODO probably should be private should not be necessary
234     // to be exposed at all only used in lang providers at the moment
235     // to generate URL for script, editors should use a model of script
236     // source and not interact with the URL
237     // Also if it is to remain needs to be renamed to getParcelLocationURL
238 
239     // return  URL string  to parcel
240     public String getParcelLocation()
241     {
242         return parent.getPathToParcel();
243     }
244 
245 
246     public String toString()
247     {
248         return "\nParcelLocation = " + getParcelLocation() + "\nLocationPlaceHolder = " + locationPlaceHolder + super.toString();
249     }
250 
251     public URL[] getClassPath() throws java.net.MalformedURLException
252     {
253     try
254     {
255         String classpath = (String)getLanguageProperties().get("classpath");
256         Vector paths = null;
257 
258         if ( classpath == null )
259         {
260             classpath = "";
261         }
262 
263         String parcelPath = getParcelLocation();
264         // make sure path ends with /
265         if ( !parcelPath.endsWith("/") )
266         {
267             parcelPath += "/";
268         }
269 
270         // replace \ with /
271         parcelPath = parcelPath.replace( '\\', '/' );
272 
273         Vector classPathVec =  new Vector();
274         StringTokenizer stk = new StringTokenizer(classpath, ":");
275         while (  stk.hasMoreElements() )
276         {
277             String relativeClasspath =  (String)stk.nextElement();
278             String pathToProcess  = PathUtils.make_url( parcelPath, relativeClasspath);
279             URL url = createURL( pathToProcess );
280             if ( url != null )
281             {
282                 classPathVec.add (  url  );
283             }
284 
285         }
286         if ( classPathVec.size() == 0)
287         {
288             URL url = createURL( parcelPath );
289             if ( url != null )
290             {
291                 classPathVec.add(url);
292             }
293         }
294 
295         return  (URL[])classPathVec.toArray( new URL[0]);
296     }
297     catch ( Exception e )
298     {
299         LogUtils.DEBUG("Failed to build class path " + e.toString() );
300         LogUtils.DEBUG( LogUtils.getTrace( e ) );
301         return new URL[0];
302     }
303 
304     }
305     private URL createURL( String path ) throws java.net.MalformedURLException
306     {
307         URL url = null;
308         int indexOfColon = path.indexOf(":");
309         String scheme = path.substring( 0, indexOfColon );
310         UCBStreamHandler handler = new UCBStreamHandler( parent.parent.m_xCtx, scheme, parent.m_xSFA);
311 
312         path += UCBStreamHandler.separator;
313         url = new URL(null, path, handler);
314         return url;
315     }
316 
317     // TODO should decide whether this should throw or not
318     // decide whether it should be public or protected ( final ? )
319     public void loadSource()
320     {
321             try
322             {
323                 URL sourceUrl = getSourceURL();
324                 LogUtils.DEBUG("** In load source BUT not loading yet for " + sourceUrl );
325 
326                 if ( sourceUrl != null )
327                 {
328                     StringBuffer buf = new StringBuffer();
329                     InputStream in = sourceUrl.openStream();
330 
331                     byte[] contents = new byte[1024];
332                     int len = 0;
333 
334                     while ((len = in.read(contents, 0, 1024)) != -1) {
335                         buf.append(new String(contents, 0, len));
336                     }
337 
338                     try {
339                         in.close();
340                     }
341                     catch (java.io.IOException ignore ) {
342                         LogUtils.DEBUG("** Failed to read scriot from url " + ignore.toString() );
343                     }
344 
345                     source = buf.toString();
346                     hasSource = true;
347                 }
348             }
349             catch (java.io.IOException e) {
350                 LogUtils.DEBUG("** Failed to read scriot from url " + e.toString());
351             }
352 
353         }
354     protected boolean writeSourceFile()
355     {
356         String parcelLocation = parent.getPathToParcel();
357         String sourceFilePath = parent.getPathToParcel() + "/" + getLanguageName();
358         boolean result = false;
359         OutputStream os = null;
360         try
361         {
362             XSimpleFileAccess2 xSFA2 = ( XSimpleFileAccess2 )
363                 UnoRuntime.queryInterface( XSimpleFileAccess2.class,
364                     parent.m_xSFA );
365             if ( xSFA2 != null )
366             {
367                 ByteArrayInputStream bis = new ByteArrayInputStream( getSourceBytes() );
368                 XInputStreamImpl xis = new XInputStreamImpl( bis );
369                 xSFA2.writeFile( sourceFilePath, xis );
370                 xis.closeInput();
371                 result = true;
372             }
373         }
374         // TODO re-examine exception processing should probably throw
375         // exceptions back to caller
376         catch ( Exception ignore )
377 
378         {
379         }
380         return result;
381     }
382     protected boolean removeSourceFile()
383     {
384         String parcelLocation = parent.getPathToParcel();
385         String sourceFilePath = parcelLocation + "/" + getLanguageName();
386         boolean result = false;
387         try
388         {
389             parent.m_xSFA.kill( sourceFilePath );
390             result = true;
391         }
392         // TODO reexamine exception handling
393         catch ( Exception e )
394         {
395         }
396         return result;
397     }
398 
399     public URL getSourceURL() throws java.net.MalformedURLException
400     {
401         String sUrl = null;
402         URL scriptURL = null;
403 
404         sUrl = getParcelLocation();
405         sUrl = PathUtils.make_url( sUrl, getLanguageName() );
406         LogUtils.DEBUG("Creating script url for " + sUrl );
407         scriptURL = createURL( sUrl );
408         return scriptURL;
409     }
410 }
411