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 }