001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.ecoinformatics.seek.datasource;
031
032import java.io.BufferedOutputStream;
033import java.io.File;
034import java.io.FileOutputStream;
035import java.io.IOException;
036import java.io.InputStream;
037import java.io.OutputStream;
038import java.net.URL;
039import java.net.URLConnection;
040
041import org.apache.commons.logging.Log;
042import org.apache.commons.logging.LogFactory;
043import org.ecoinformatics.ecogrid.authenticatedqueryservice.AuthenticatedQueryServiceGetToStreamClient;
044import org.ecoinformatics.ecogrid.queryservice.QueryServiceGetToStreamClient;
045import org.ecoinformatics.seek.ecogrid.EcoGridService;
046import org.ecoinformatics.seek.ecogrid.EcoGridServicesController;
047import org.kepler.configuration.ConfigurationManager;
048import org.kepler.configuration.ConfigurationProperty;
049import org.kepler.objectmanager.cache.BufferedDataCacheObject;
050import org.kepler.objectmanager.cache.CacheManager;
051
052import ptolemy.util.CancelException;
053import ptolemy.util.MessageHandler;
054
055/**
056 * This class is not as generic as the name may indicate. It is designed to get
057 * the metadata to determine where the data is stored and then does a Ecogrid
058 * "get" to the data.
059 */
060public class EcogridDataCacheItem extends BufferedDataCacheObject {
061        protected String mEndPoint = null;
062        private boolean mIsTarFile = false;
063        private String mEntityIdentifier = null;
064
065        private static Log log;
066        static {
067                log = LogFactory
068                                .getLog("org.ecoinformatics.seek.datasource.EcogridDataCacheItem");
069        }
070
071        /**
072         * Default constructor
073         * 
074         */
075        public EcogridDataCacheItem() {
076                super();
077        }
078
079        /*
080         * (non-Javadoc)
081         * 
082         * @see org.ecoinformatics.seek.datasource.DataCacheItem#doWork()
083         */
084        public int doWork() {
085                log.debug("EcogridDataCacheItem - doing Work mStatus " + getStatus());
086                return downloadDataFromSource();
087        }
088
089        /**
090         * This method will download data base on distribution url in entity object
091         */
092        protected int downloadDataFromSource() {
093
094                String resourceName = getResourceName();
095                return getContentFromSource(resourceName);
096
097        }
098
099        /*
100         * Method to get content from given source.
101         */
102        private int getContentFromSource(String resourceName) {
103                log.debug("download data from EcogridDataCacheItem URL : "
104                                + resourceName);
105                if (resourceName.startsWith("http://")
106                                || resourceName.startsWith("file://")
107                                || resourceName.startsWith("ftp://")) {
108                        // get the data from a URL
109                        FileOutputStream osw = null;
110                        try {
111                                URL url = new URL(resourceName);
112                                if (url != null) {
113                                        URLConnection conn = url.openConnection();
114                                        if (conn != null) {
115                                                InputStream filestream = url.openStream();
116                                                if (filestream != null) {
117
118                                                        // String type = conn.getContentType();
119
120                                                        // Crate a new Cache Filename and write the
121                                                        // resultsets directly to the cached file
122                                                        File localFile = getFile();
123                                                        osw = new FileOutputStream(localFile);
124                                                        if (osw != null) {
125                                                                byte[] c = new byte[1024];
126                                                                int bread = filestream.read(c, 0, 1024);
127                                                                while (bread != -1) {
128                                                                        osw.write(c, 0, bread);
129                                                                        bread = filestream.read(c, 0, 1024);
130                                                                }
131                                                                osw.close();
132                                                                return CACHE_COMPLETE;
133                                                        }
134
135                                                }
136                                        }
137                                }
138                                log
139                                                .debug("EcogridDataCacheItem - error connecting to http/file ");
140                                cleanUpCache(osw);
141                                return CACHE_ERROR;
142                        } catch (IOException ioe) {
143                                cleanUpCache(osw);
144                                return CACHE_ERROR;
145                        }
146
147                        // We will use ecogrid client to handle both ecogrid and srb
148                        // protocol
149                } else if (resourceName.startsWith("ecogrid://")) {
150                        // get the docid from url
151                        int start = resourceName.indexOf("/", 11) + 1;
152                        log.debug("start: " + start);
153                        int end = resourceName.indexOf("/", start);
154                        if (end == -1) {
155                                end = resourceName.length();
156                        }
157                        log.debug("end: " + end);
158                        String identifier = resourceName.substring(start, end);
159                        // pass this docid and get data item
160                        return getDataItemFromEcoGrid(mEndPoint, identifier);
161                } else if (resourceName.startsWith("srb://")) {
162                        // get srb docid from the url
163                        String identifier = transformSRBurlToDocid(resourceName);
164                        // reset endpoint for srb (This is hack we need to figure ou
165                        // elegent way to do this
166                        
167      ConfigurationProperty commonProperty = ConfigurationManager
168        .getInstance().getProperty(ConfigurationManager.getModule("ecogrid"));
169      mEndPoint = commonProperty.getProperty("srb.endPoint").getValue();
170                        // pass this docid and get data item
171                        log.debug("before get srb data@@@@@@@@@@@@@@@@@@@@@@@@@@");
172                        return getDataItemFromEcoGrid(mEndPoint, identifier);
173                } else {
174                        return CACHE_ERROR;
175                }
176        }
177
178        /**
179         * 
180         *       */
181        protected String getAttrsForXML() {
182                return "   endpoint=\"" + mEndPoint + "\"\n";
183
184        }
185
186        /**
187         * @return Returns the mEndPoint.
188         */
189        public String getEndPoint() {
190                return mEndPoint;
191        }
192
193        /**
194         * @param endPoint
195         *            The mEndPoint to set.
196         */
197        public void setEndPoint(String endPoint) {
198                mEndPoint = endPoint;
199        }
200
201        /**
202         * If this item is a tar file
203         * 
204         * @return boolean
205         */
206        public boolean getIsTarFile() {
207                return mIsTarFile;
208        }
209
210        /**
211         * Set this item is tar file or not
212         * 
213         * @param isTarFile
214         *            boolean
215         */
216        public void setIsTarFile(boolean isTarFile) {
217                mIsTarFile = isTarFile;
218        }
219
220        /*
221         * This method will transfer a srb url to srb docid in ecogrid ecogrid srb
222         * id should look like:
223         * srb://seek:/home/beam.seek/IPCC_climate/Present/ccld6190.dat and
224         * correspond docid looks like:
225         * srb://testuser:TESTUSER@orion.sdsc.edu/home/beam
226         * .seek/IPCC_climate/Present/ccld6190.dat
227         */
228        private String transformSRBurlToDocid(String srbURL) {
229                String docid = null;
230                if (srbURL == null) {
231                        return docid;
232                }
233                String regex = "seek:";
234                srbURL = srbURL.trim();
235                log.debug("The srb url is " + srbURL);
236                // get user name , passwd and machine namefrom configure file
237    ConfigurationProperty commonProperty = ConfigurationManager
238        .getInstance().getProperty(ConfigurationManager.getModule("ecogrid"));
239    String user = commonProperty.getProperty("srb.user").getValue();
240    String passwd = commonProperty.getProperty("srb.passwd").getValue();
241    String machineName = commonProperty.getProperty("srb.machineName").getValue();
242    
243                String replacement = user + ":" + passwd + "@" + machineName;
244                docid = srbURL.replaceFirst(regex, replacement);
245                log.debug("The srb id is " + docid);
246                return docid;
247        }
248
249        /**
250         * Set an entity to describe the data cache
251         * 
252         * @param mEntity
253         *            Entity
254         */
255        public void setEntityIdentifier(String identifier) {
256                this.mEntityIdentifier = identifier;
257        }
258
259        /**
260         * Get an entity to describe the data cache
261         * 
262         * @return Entity
263         */
264        public String getEntityIdentifier() {
265                return mEntityIdentifier;
266        }
267
268        /*
269         * This method will get data from ecogrid server base on given docid. This
270         * method will handle the distribution url is ecogrid or srb protocol
271         */
272        /**
273         * Gets the dataItemFromEcoGrid attribute of the DataCacheObject object
274         * 
275         *@param endPoint
276         *@param identifier
277         */
278        protected int getDataItemFromEcoGrid(String endPoint, String identifier) {
279
280                // create a ecogrid client object and get the full record from the
281                // client
282                if (endPoint != null && identifier != null) {
283                        log.debug("Get " + identifier + " from " + endPoint);
284                        BufferedOutputStream bos = null;
285                        try {
286                                // factory
287                                log.debug("This is instance pattern");
288
289                                URL endPointURL = new URL(endPoint);
290
291                                log.debug("Get from EcoGrid: " + identifier);
292                                // log.warn("the local file name is "+getFile());
293                                bos = new BufferedOutputStream(new FileOutputStream(getFile()));
294                                // log.warn("after create output stream ");
295                                // get the service from the controller
296                                EcoGridService service = EcoGridServicesController
297                                                .getInstance().getService(endPoint);
298                                // check if we need to authenticate for it
299                                if (service != null
300                                                && service
301                                                                .getServiceType()
302                                                                .equals(
303                                                                                EcoGridServicesController.AUTHENTICATEDQUERYSERVICETYPE)) {
304                                        // get a credential (hopefully)
305                                        String sessionId = EcoGridServicesController.getInstance()
306                                                        .authenticateForService(service);
307                                        log.info("using authenticated ecogrid get() method");
308                                        AuthenticatedQueryServiceGetToStreamClient authGetClient = new AuthenticatedQueryServiceGetToStreamClient(
309                                                        endPointURL);
310                                        authGetClient.get(identifier, sessionId, bos);
311                                } else {
312                                        // just get using the public version
313                                        // log.warn("in public version branch ");
314                                        QueryServiceGetToStreamClient ecogridClient = new QueryServiceGetToStreamClient(
315                                                        endPointURL);
316                                        // log.warn("after create service client ");
317                                        ecogridClient.get(identifier, bos);
318                                        // log.warn("after stream data  ");
319                                }
320                                // log.warn("before fulsh and close output stream ");
321                                bos.flush();
322                                bos.close();
323                                // log.warn("afer fulsh and close output stream ");
324                                return CACHE_COMPLETE;
325
326                        } catch (Exception ee) {
327                                log.error(
328                                                "EcogridDataCacheItem - error connecting to Ecogrid ",
329                                                ee);
330                                cleanUpCache(bos);
331                                // Alert user about possible permission issue (BRL:20070918)
332                                try {
333                                        MessageHandler
334                                                        .warning("There has been a problem accessing the remote data:\n"
335                                                                        + ee.getMessage());
336                                } catch (CancelException e) {
337                                        // do nothing
338                                }
339
340                                return CACHE_ERROR;
341                        }
342
343                } else {
344                        // System.out.println("in else path of get data from other source");
345                        // this is not ecogrid source, we need download by other protocol
346                        return getContentFromSource(identifier);
347
348                }
349        }
350
351        /*
352         * Cleanup the cache object if some error happens during the search.
353         */
354        private void cleanUpCache(OutputStream bos) {
355
356                // clean up the cache object
357                try {
358                        // log.warn("close the input stream and delete existed file");
359                        bos.close();
360                        // getFile().delete();
361                        if (this.getLSID() != null) {
362                                CacheManager.getInstance().removeObject(this.getLSID());
363                        }
364
365                } catch (Exception e) {
366                        log.warn("Couldn't close the output stream to cache file "
367                                        + e.getMessage());
368                }
369
370        }
371
372}