001    /*
002     * Copyright 2005 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.transit.local;
020    
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.FileInputStream;
024    import java.io.OutputStream;
025    import java.io.FileOutputStream;
026    import java.io.File;
027    import java.net.URI;
028    import java.net.URL;
029    import java.net.URLConnection;
030    import java.security.AccessController;
031    import java.security.PrivilegedExceptionAction;
032    import java.security.PrivilegedActionException;
033    import java.security.PrivilegedAction;
034    
035    import net.dpml.transit.Transit;
036    import net.dpml.transit.Artifact;
037    
038    /**
039     * The local URL protocol connection implementation.
040     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
041     * @version 1.1.0
042     */
043    public class LocalURLConnection extends URLConnection
044    {
045        private boolean m_connected;
046    
047        private File m_target;
048    
049        /**
050         * Creation of a new local handler.
051         * @param url the url to establish a connection with
052         * @exception NullPointerException if the url argument is null
053         */
054        LocalURLConnection( URL url )
055            throws NullPointerException
056        {
057            super( url );
058    
059            m_connected = false;
060        }
061    
062       /**
063        * Establish a connection.
064        *
065        * @exception IOException is an error occurs while attempting to establish
066        *  the connection.
067        */
068        public void connect()
069            throws IOException
070        {
071            if( m_connected )
072            {
073                return;
074            }
075    
076            m_connected = true;
077            
078            try
079            {
080                AccessController.doPrivileged( 
081                  new PrivilegedExceptionAction()
082                  {
083                    public Object run()
084                        throws IOException
085                    {
086                        String spec = url.toExternalForm();
087                        try
088                        {
089                            Artifact artifact = Artifact.createArtifact( spec );
090                            String groupSpec = artifact.getGroup();
091                            String artifactName = artifact.getName();
092                            String typeSpec = artifact.getType();
093                            String versionSpec = artifact.getVersion();
094                            File prefs = Transit.DPML_PREFS;
095                            File group = new File( prefs, groupSpec );
096                            File type = new File( group, typeSpec + "s" );
097                            if( null == versionSpec )
098                            {
099                                final String filename = artifactName + "." + typeSpec;
100                                m_target = new File( type, filename );
101                            }
102                            else
103                            {
104                                final String filename = artifactName + "-" + versionSpec + "." + typeSpec;
105                                m_target = new File( type, filename );
106                            }
107                        }
108                        catch( Throwable e )
109                        {
110                            String message = e.getMessage();
111                            IOException exception = new IOException( message );
112                            exception.initCause( e.getCause() );
113                            throw exception;
114                        }
115                        return null; // nothing to return
116                    }
117                  }
118                );
119            } 
120            catch( PrivilegedActionException e )
121            {
122                throw (IOException) e.getException();
123            } 
124        }
125    
126       /**
127        * Return an input stream to the resource.
128        * @return the input stream
129        * @exception IOException is an error occurs
130        */
131        public InputStream getInputStream()
132            throws IOException
133        {
134            connect();
135            if( m_target == null )
136            {
137                return null;
138            }
139            else
140            {
141                return new FileInputStream( m_target );
142            }
143        }
144    
145       /**
146        * Return an output stream to the resource.
147        * @return the output stream
148        * @exception IOException if any I/O problems occur.
149        */
150        public OutputStream getOutputStream()
151            throws IOException
152        {
153            connect();
154            if( m_target == null )
155            {
156                return null;
157            }
158            else
159            {
160                if( !m_target.exists() )
161                {
162                    File parent = m_target.getParentFile();
163                    if( null != parent )
164                    {
165                        parent.mkdirs();
166                    }
167                    m_target.createNewFile();
168                }
169                return new FileOutputStream( m_target );
170            }
171        }
172    
173       /**
174        * Return the content for this local resource.
175        * @param classes a sequence of classes against which the
176        *   implementation will attempt to establish a known match
177        * @return the content object (possibly null)
178        * @exception IOException is an error occurs
179        */
180        public Object getContent( final Class[] classes )
181            throws IOException
182        {
183            connect();
184            Object result = AccessController.doPrivileged( 
185              new PrivilegedAction()
186              {
187                public Object run()
188                {
189                    for( int i=0; i < classes.length; i++ )
190                    {
191                        Class c = classes[i];
192                        if( c.equals( File.class ) )
193                        {
194                            return m_target;
195                        }
196                    }
197                    return null;
198                }
199              }
200            );
201    
202            if( null != result )
203            {
204                return result;
205            }
206            else
207            {
208                if( null != m_target )
209                {
210                    URI uri = m_target.toURI();
211                    URL url = uri.toURL();
212                    return url.getContent( classes );
213                }
214                else
215                {
216                    return super.getContent( classes );
217                }
218            }
219        }
220    }