Ignore:
Timestamp:
2017-09-16T01:37:46+02:00 (7 years ago)
Author:
donvip
Message:

fix #josm15159 - add compatibility with new JOSM plugin classloader mechanism. Java does not allow for a class A to access a package-scope class B in the same package if they don't share the same classloader

Location:
applications/editors/josm/plugins/opendata
Files:
4 added
1 deleted
3 edited
1 copied

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/OdPlugin.java

    r33518 r33613  
    6363            instance = this;
    6464        } else {
    65             throw new IllegalAccessError("Cannot instantiate plugin twice !");
     65            throw new IllegalStateException("Cannot instantiate plugin twice !");
    6666        }
    6767        // Allow JOSM to import more files
  • applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/geographic/MifTabImporter.java

    r32545 r33613  
    3333                return TabReader.parseDataSet(in, file, handler, instance);
    3434            }
    35         } catch (IOException e) {
     35        } catch (IOException | IllegalArgumentException e) {
    3636            throw new IllegalDataException(e);
    3737        }
  • applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/geographic/TabFiles.java

    r33609 r33613  
    1 //    JOSM opendata plugin.
    2 //    Copyright (C) 2011-2012 Don-vip
    3 //
    4 //    This program is free software: you can redistribute it and/or modify
    5 //    it under the terms of the GNU General Public License as published by
    6 //    the Free Software Foundation, either version 3 of the License, or
    7 //    (at your option) any later version.
    8 //
    9 //    This program is distributed in the hope that it will be useful,
    10 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
    11 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12 //    GNU General Public License for more details.
    13 //
    14 //    You should have received a copy of the GNU General Public License
    15 //    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16 package org.geotools.data.shapefile.files;
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.plugins.opendata.core.io.geographic;
    173
    184import static org.geotools.data.shapefile.files.ShpFileType.SHP;
    195
    206import java.io.File;
    21 import java.io.FileOutputStream;
    227import java.io.FilenameFilter;
    23 import java.io.FilterInputStream;
    24 import java.io.FilterOutputStream;
    25 import java.io.IOException;
    26 import java.io.InputStream;
    27 import java.io.OutputStream;
    28 import java.io.RandomAccessFile;
     8import java.lang.reflect.Field;
    299import java.net.MalformedURLException;
    3010import java.net.URL;
    31 import java.net.URLConnection;
    32 import java.nio.MappedByteBuffer;
    33 import java.nio.channels.Channels;
    34 import java.nio.channels.FileChannel;
    35 import java.nio.channels.FileChannel.MapMode;
    36 import java.nio.channels.ReadableByteChannel;
    37 import java.nio.channels.WritableByteChannel;
    38 import java.util.ArrayList;
    39 import java.util.Collection;
    4011import java.util.HashMap;
    4112import java.util.Map;
    4213import java.util.Map.Entry;
    4314import java.util.Set;
    44 import java.util.concurrent.ConcurrentHashMap;
    45 import java.util.concurrent.locks.ReentrantReadWriteLock;
    46 import java.util.logging.Level;
    4715
    4816import org.geotools.data.DataUtilities;
     17import org.geotools.data.shapefile.files.ShpFileType;
     18import org.geotools.data.shapefile.files.ShpFiles;
     19import org.openstreetmap.josm.tools.JosmRuntimeException;
    4920import org.openstreetmap.josm.tools.Logging;
     21import org.openstreetmap.josm.tools.Utils;
    5022
    5123/**
    52  * Ugly copy of ShpFiles class modified to fit MapInfo TAB needs.
     24 * Extension of {@link ShpFiles} class modified to fit MapInfo TAB needs.
    5325 */
    5426public class TabFiles extends ShpFiles {
     
    5830     * key is the type of file
    5931     */
    60     private final Map<ShpFileType, URL> urls = new ConcurrentHashMap<>();
    61 
    62     /**
    63      * A read/write lock, so that we can have concurrent readers
    64      */
    65     private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    66 
    67     /**
    68      * The set of locker sources per thread. Used as a debugging aid and to upgrade/downgrade
    69      * the locks
    70      */
    71     private final Map<Thread, Collection<ShpFilesLocker>> lockers = new ConcurrentHashMap<>();
    72 
    73     /**
    74      * A cache for read only memory mapped buffers
    75      */
    76     private final MemoryMapCache mapCache = new MemoryMapCache();
    77 
    78     private boolean memoryMapCacheEnabled;
    79 
     32    private final Map<ShpFileType, URL> urls;
    8033
    8134    ////////////////////////////////////////////////////
    8235
     36    @SuppressWarnings("unchecked")
    8337    public TabFiles(File headerFile, File dataFile) throws IllegalArgumentException {
    8438        super(fakeShpFile(headerFile)); // Useless but necessary
     39
     40        try {
     41            Field furls = ShpFiles.class.getDeclaredField("urls");
     42            Utils.setObjectsAccessible(furls);
     43            urls = (Map<ShpFileType, URL>) furls.get(this);
     44        } catch (ReflectiveOperationException e) {
     45            throw new JosmRuntimeException(e);
     46        }
     47
    8548        init(DataUtilities.fileToURL(headerFile));
    8649        urls.put(ShpFileType.DBF, DataUtilities.fileToURL(dataFile));
     
    8851
    8952    /**
    90      * This is really ugly. Used only to give a fake shp file to ShpFiles constructor to avoid IllegalArgument at initialization.
     53     * Used only to give a fake shp file to ShpFiles constructor to avoid IllegalArgument at initialization.
    9154     */
    9255    private static URL fakeShpFile(File headerFile) {
     
    143106        // different cases that the extension can be made up of.
    144107        // IE Shp, SHP, Shp, ShP etc...
    145         if (isLocalTab()) {
     108        if (isLocal()) {
    146109            Set<Entry<ShpFileType, URL>> entries = urls.entrySet();
    147110            Map<ShpFileType, URL> toUpdate = new HashMap<>();
    148111            for (Entry<ShpFileType, URL> entry : entries) {
    149                 if( !existsTab(entry.getKey()) ){
     112                if (!exists(entry.getKey())) {
    150113                    url = findExistingFile(entry.getKey(), entry.getValue());
    151                     if( url!=null ){
     114                    if (url != null) {
    152115                        toUpdate.put(entry.getKey(), url);
    153116                    }
     
    161124        final File file = DataUtilities.urlToFile(value);
    162125        File directory = file.getParentFile();
    163         if( directory==null || !directory.exists() ) {
    164             // doesn't exist
    165             return null;
    166         }
    167         File[] files = directory.listFiles(new FilenameFilter(){
    168 
    169             @Override
    170             public boolean accept(File dir, String name) {
    171                 return file.getName().equalsIgnoreCase(name);
    172             }
    173 
    174         });
    175         if( files.length>0 ){
    176             try {
    177                 return files[0].toURI().toURL();
    178             } catch (MalformedURLException e) {
    179                 Logging.error(e);
     126        if (directory != null && directory.exists()) {
     127            File[] files = directory.listFiles((FilenameFilter) (dir, name) -> file.getName().equalsIgnoreCase(name));
     128            if (files.length > 0) {
     129                try {
     130                    return files[0].toURI().toURL();
     131                } catch (MalformedURLException e) {
     132                    Logging.error(e);
     133                }
    180134            }
    181135        }
     
    193147
    194148    @Override
    195     public void dispose() {
    196         if (numberOfLocks() != 0) {
    197             logCurrentLockers(Level.SEVERE);
    198             lockers.clear(); // so as not to get this log again.
    199         }
    200         mapCache.clean();
    201     }
    202 
    203     /**
    204      * Writes to the log all the lockers and when they were constructed.
    205      *
    206      * @param logLevel
    207      *                the level at which to log.
    208      */
    209     @Override
    210     public void logCurrentLockers(Level logLevel) {
    211         for (Collection<ShpFilesLocker> lockerList : lockers.values()) {
    212             for (ShpFilesLocker locker : lockerList) {
    213                 StringBuilder sb = new StringBuilder("The following locker still has a lock: ");
    214                 sb.append(locker);
    215                 Logging.error(sb.toString());
    216             }
    217         }
    218     }
    219 
    220     /**
    221      * Returns the URLs (in string form) of all the files for the shapefile
    222      * datastore.
    223      *
    224      * @return the URLs (in string form) of all the files for the shapefile
    225      *         datastore.
    226      */
    227     @Override
    228     public Map<ShpFileType, String> getFileNames() {
    229         Map<ShpFileType, String> result = new HashMap<>();
    230         Set<Entry<ShpFileType, URL>> entries = urls.entrySet();
    231 
    232         for (Entry<ShpFileType, URL> entry : entries) {
    233             result.put(entry.getKey(), entry.getValue().toExternalForm());
    234         }
    235 
    236         return result;
    237     }
    238 
    239     /**
    240      * Returns the string form of the url that identifies the file indicated by
    241      * the type parameter or null if it is known that the file does not exist.
    242      *
    243      * <p>
    244      * Note: a URL should NOT be constructed from the string instead the URL
    245      * should be obtained through calling one of the aquireLock methods.
    246      *
    247      * @param type
    248      *                indicates the type of file the caller is interested in.
    249      *
    250      * @return the string form of the url that identifies the file indicated by
    251      *         the type parameter or null if it is known that the file does not
    252      *         exist.
    253      */
    254     @Override
    255     public String get(ShpFileType type) {
    256         return urls.get(type).toExternalForm();
    257     }
    258 
    259     /**
    260      * Returns the number of locks on the current set of shapefile files. This
    261      * is not thread safe so do not count on it to have a completely accurate
    262      * picture but it can be useful debugging
    263      *
    264      * @return the number of locks on the current set of shapefile files.
    265      */
    266     @Override
    267     public int numberOfLocks() {
    268         int count = 0;
    269         for (Collection<ShpFilesLocker> lockerList : lockers.values()) {
    270             count += lockerList.size();
    271         }
    272         return count;
    273     }
    274     /**
    275      * Acquire a File for read only purposes. It is recommended that get*Stream or
    276      * get*Channel methods are used when reading or writing to the file is
    277      * desired.
    278      *
    279      *
    280      * @see #getInputStream(ShpFileType, FileReader)
    281      * @see #getReadChannel(ShpFileType, FileReader)
    282      * @see #getWriteChannel(ShpFileType, FileReader)
    283      *
    284      * @param type
    285      *                the type of the file desired.
    286      * @param requestor
    287      *                the object that is requesting the File. The same object
    288      *                must release the lock and is also used for debugging.
    289      * @return the File type requested
    290      */
    291     @Override
    292     public File acquireReadFile(ShpFileType type,
    293             FileReader requestor) {
    294         if(!isLocalTab() ){
    295             throw new IllegalStateException("This method only applies if the files are local");
    296         }
    297         URL url = acquireRead(type, requestor);
    298         return DataUtilities.urlToFile(url);
    299     }
    300 
    301     /**
    302      * Acquire a URL for read only purposes.  It is recommended that get*Stream or
    303      * get*Channel methods are used when reading or writing to the file is
    304      * desired.
    305      *
    306      *
    307      * @see #getInputStream(ShpFileType, FileReader)
    308      * @see #getReadChannel(ShpFileType, FileReader)
    309      * @see #getWriteChannel(ShpFileType, FileReader)
    310      *
    311      * @param type
    312      *                the type of the file desired.
    313      * @param requestor
    314      *                the object that is requesting the URL. The same object
    315      *                must release the lock and is also used for debugging.
    316      * @return the URL to the file of the type requested
    317      */
    318     @Override
    319     public URL acquireRead(ShpFileType type, FileReader requestor) {
    320         URL url = urls.get(type);
    321         if (url == null)
    322             return null;
    323 
    324         readWriteLock.readLock().lock();
    325         Collection<ShpFilesLocker> threadLockers = getCurrentThreadLockers();
    326         threadLockers.add(new ShpFilesLocker(url, requestor));
    327         return url;
    328     }
    329 
    330     /**
    331      * Tries to acquire a URL for read only purposes. Returns null if the
    332      * acquire failed or if the file does not.
    333      * <p> It is recommended that get*Stream or
    334      * get*Channel methods are used when reading or writing to the file is
    335      * desired.
    336      * </p>
    337      *
    338      * @see #getInputStream(ShpFileType, FileReader)
    339      * @see #getReadChannel(ShpFileType, FileReader)
    340      * @see #getWriteChannel(ShpFileType, FileReader)
    341      *
    342      * @param type
    343      *                the type of the file desired.
    344      * @param requestor
    345      *                the object that is requesting the URL. The same object
    346      *                must release the lock and is also used for debugging.
    347      * @return A result object containing the URL or the reason for the failure.
    348      */
    349     @Override
    350     public Result<URL, State> tryAcquireRead(ShpFileType type,
    351             FileReader requestor) {
    352         URL url = urls.get(type);
    353         if (url == null) {
    354             return new Result<>(null, State.NOT_EXIST);
    355         }
    356 
    357         boolean locked = readWriteLock.readLock().tryLock();
    358         if (!locked) {
    359             return new Result<>(null, State.LOCKED);
    360         }
    361 
    362         getCurrentThreadLockers().add(new ShpFilesLocker(url, requestor));
    363 
    364         return new Result<>(url, State.GOOD);
    365     }
    366 
    367     /**
    368      * Unlocks a read lock. The file and requestor must be the the same as the
    369      * one of the lockers.
    370      *
    371      * @param file
    372      *                file that was locked
    373      * @param requestor
    374      *                the class that requested the file
    375      */
    376     @Override
    377     public void unlockRead(File file, FileReader requestor) {
    378         Collection<URL> allURLS = urls.values();
    379         for (URL url : allURLS) {
    380             if (DataUtilities.urlToFile(url).equals(file)) {
    381                 unlockRead(url, requestor);
    382             }
    383         }
    384     }
    385 
    386     /**
    387      * Unlocks a read lock. The url and requestor must be the the same as the
    388      * one of the lockers.
    389      *
    390      * @param url
    391      *                url that was locked
    392      * @param requestor
    393      *                the class that requested the url
    394      */
    395     @Override
    396     public void unlockRead(URL url, FileReader requestor) {
    397         if (url == null) {
    398             throw new NullPointerException("url cannot be null");
    399         }
    400         if (requestor == null) {
    401             throw new NullPointerException("requestor cannot be null");
    402         }
    403 
    404         Collection<ShpFilesLocker> threadLockers = getCurrentThreadLockers();
    405         boolean removed = threadLockers.remove(new ShpFilesLocker(url, requestor));
    406         if (!removed) {
    407             throw new IllegalArgumentException(
    408                     "Expected requestor "
    409                             + requestor
    410                             + " to have locked the url but it does not hold the lock for the URL");
    411         }
    412         if(threadLockers.size() == 0)
    413             lockers.remove(Thread.currentThread());
    414         readWriteLock.readLock().unlock();
    415     }
    416 
    417     /**
    418      * Acquire a File for read and write purposes.
    419      * <p> It is recommended that get*Stream or
    420      * get*Channel methods are used when reading or writing to the file is
    421      * desired.
    422      * </p>
    423      *
    424      * @see #getInputStream(ShpFileType, FileReader)
    425      * @see #getReadChannel(ShpFileType, FileReader)
    426      * @see #getWriteChannel(ShpFileType, FileReader)
    427 
    428      *
    429      * @param type
    430      *                the type of the file desired.
    431      * @param requestor
    432      *                the object that is requesting the File. The same object
    433      *                must release the lock and is also used for debugging.
    434      * @return the File to the file of the type requested
    435      */
    436     @Override
    437     public File acquireWriteFile(ShpFileType type,
    438             FileWriter requestor) {
    439         if(!isLocalTab() ){
    440             throw new IllegalStateException("This method only applies if the files are local");
    441         }
    442         URL url = acquireWrite(type, requestor);
    443         return DataUtilities.urlToFile(url);
    444     }
    445     /**
    446      * Acquire a URL for read and write purposes.
    447      * <p> It is recommended that get*Stream or
    448      * get*Channel methods are used when reading or writing to the file is
    449      * desired.
    450      * </p>
    451      *
    452      * @see #getInputStream(ShpFileType, FileReader)
    453      * @see #getReadChannel(ShpFileType, FileReader)
    454      * @see #getWriteChannel(ShpFileType, FileReader)
    455 
    456      *
    457      * @param type
    458      *                the type of the file desired.
    459      * @param requestor
    460      *                the object that is requesting the URL. The same object
    461      *                must release the lock and is also used for debugging.
    462      * @return the URL to the file of the type requested
    463      */
    464     @Override
    465     public URL acquireWrite(ShpFileType type, FileWriter requestor) {
    466         URL url = urls.get(type);
    467         if (url == null) {
    468             return null;
    469         }
    470 
    471         // we need to give up all read locks before getting the write one
    472         Collection<ShpFilesLocker> threadLockers = getCurrentThreadLockers();
    473         relinquishReadLocks(threadLockers);
    474         readWriteLock.writeLock().lock();
    475         threadLockers.add(new ShpFilesLocker(url, requestor));
    476         mapCache.cleanFileCache(url);
    477         return url;
    478     }
    479 
    480     /**
    481      * Tries to acquire a URL for read/write purposes. Returns null if the
    482      * acquire failed or if the file does not exist
    483      * <p> It is recommended that get*Stream or
    484      * get*Channel methods are used when reading or writing to the file is
    485      * desired.
    486      * </p>
    487      *
    488      * @see #getInputStream(ShpFileType, FileReader)
    489      * @see #getReadChannel(ShpFileType, FileReader)
    490      * @see #getWriteChannel(ShpFileType, FileReader)
    491 
    492      *
    493      * @param type
    494      *                the type of the file desired.
    495      * @param requestor
    496      *                the object that is requesting the URL. The same object
    497      *                must release the lock and is also used for debugging.
    498      * @return A result object containing the URL or the reason for the failure.
    499      */
    500     @Override
    501     public Result<URL, State> tryAcquireWrite(ShpFileType type,
    502             FileWriter requestor) {
    503 
    504         URL url = urls.get(type);
    505         if (url == null) {
    506             return new Result<>(null, State.NOT_EXIST);
    507         }
    508 
    509         Collection<ShpFilesLocker> threadLockers = getCurrentThreadLockers();
    510         boolean locked = readWriteLock.writeLock().tryLock();
    511         if (!locked && threadLockers.size() > 1) {
    512             // hum, it may be be because we are holding a read lock
    513             relinquishReadLocks(threadLockers);
    514             locked = readWriteLock.writeLock().tryLock();
    515             if(locked == false) {
    516                 regainReadLocks(threadLockers);
    517                 return new Result<>(null, State.LOCKED);
    518             }
    519         }
    520 
    521         threadLockers.add(new ShpFilesLocker(url, requestor));
    522         return new Result<>(url, State.GOOD);
    523     }
    524 
    525     /**
    526      * Unlocks a read lock. The file and requestor must be the the same as the
    527      * one of the lockers.
    528      *
    529      * @param file
    530      *                file that was locked
    531      * @param requestor
    532      *                the class that requested the file
    533      */
    534     @Override
    535     public void unlockWrite(File file, FileWriter requestor) {
    536         Collection<URL> allURLS = urls.values();
    537         for (URL url : allURLS) {
    538             if (DataUtilities.urlToFile(url).equals(file)) {
    539                 unlockWrite(url, requestor);
    540             }
    541         }
    542     }
    543 
    544     /**
    545      * Unlocks a read lock. The requestor must be have previously obtained a
    546      * lock for the url.
    547      *
    548      *
    549      * @param url
    550      *                url that was locked
    551      * @param requestor
    552      *                the class that requested the url
    553      */
    554     @Override
    555     public void unlockWrite(URL url, FileWriter requestor) {
    556         if (url == null) {
    557             throw new NullPointerException("url cannot be null");
    558         }
    559         if (requestor == null) {
    560             throw new NullPointerException("requestor cannot be null");
    561         }
    562         Collection<ShpFilesLocker> threadLockers = getCurrentThreadLockers();
    563         boolean removed = threadLockers.remove(new ShpFilesLocker(url, requestor));
    564         if (!removed) {
    565             throw new IllegalArgumentException(
    566                     "Expected requestor "
    567                             + requestor
    568                             + " to have locked the url but it does not hold the lock for the URL");
    569         }
    570 
    571         if(threadLockers.size() == 0) {
    572             lockers.remove(Thread.currentThread());
    573         } else {
    574             // get back read locks before giving up the write one
    575             regainReadLocks(threadLockers);
    576         }
    577         readWriteLock.writeLock().unlock();
    578     }
    579 
    580     /**
    581      * Returns the list of lockers attached to a given thread, or creates it if missing
    582      * @return
    583      */
    584     private Collection<ShpFilesLocker> getCurrentThreadLockers() {
    585         Collection<ShpFilesLocker> threadLockers = lockers.get(Thread.currentThread());
    586         if(threadLockers == null) {
    587             threadLockers = new ArrayList<>();
    588             lockers.put(Thread.currentThread(), threadLockers);
    589         }
    590         return threadLockers;
    591     }
    592 
    593     /**
    594      * Gives up all read locks in preparation for lock upgade
    595      * @param threadLockers
    596      */
    597     private void relinquishReadLocks(Collection<ShpFilesLocker> threadLockers) {
    598         for (ShpFilesLocker shpFilesLocker : threadLockers) {
    599             if(shpFilesLocker.reader != null && !shpFilesLocker.upgraded) {
    600                 readWriteLock.readLock().unlock();
    601                 shpFilesLocker.upgraded = true;
    602             }
    603         }
    604     }
    605 
    606     /**
    607      * Re-takes the read locks in preparation for lock downgrade
    608      * @param threadLockers
    609      */
    610     private void regainReadLocks(Collection<ShpFilesLocker> threadLockers) {
    611         for (ShpFilesLocker shpFilesLocker : threadLockers) {
    612             if(shpFilesLocker.reader != null && shpFilesLocker.upgraded) {
    613                 readWriteLock.readLock().lock();
    614                 shpFilesLocker.upgraded = false;
    615             }
    616         }
    617     }
    618 
    619     /**
    620      * Determine if the location of this shapefile is local or remote.
    621      *
    622      * @return true if local, false if remote
    623      */
    624     public boolean isLocalTab() {
    625         return urls.get(ShpFileType.SHP).toExternalForm().toLowerCase().startsWith("file:");
    626     }
    627 
    628     /**
    629      * Delete all the shapefile files. If the files are not local or the one
    630      * files cannot be deleted return false.
    631      */
    632     @Override
    633     public boolean delete() {
    634         BasicShpFileWriter requestor = new BasicShpFileWriter("ShpFiles for deleting all files");
    635         URL writeLockURL = acquireWrite(SHP, requestor);
    636         boolean retVal = true;
    637         try {
    638             if (isLocalTab()) {
    639                 Collection<URL> values = urls.values();
    640                 for (URL url : values) {
    641                     File f = DataUtilities.urlToFile(url);
    642                     if (!f.delete()) {
    643                         retVal = false;
    644                     }
    645                 }
    646             } else {
    647                 retVal = false;
    648             }
    649         } finally {
    650             unlockWrite(writeLockURL, requestor);
    651         }
    652         return retVal;
    653     }
    654 
    655     /**
    656      * Opens a input stream for the indicated file. A read lock is requested at
    657      * the method call and released on close.
    658      *
    659      * @param type
    660      *                the type of file to open the stream to.
    661      * @param requestor
    662      *                the object requesting the stream
    663      * @return an input stream
    664      *
    665      * @throws IOException
    666      *                 if a problem occurred opening the stream.
    667      */
    668     @Override
    669     public InputStream getInputStream(ShpFileType type,
    670             final FileReader requestor) throws IOException {
    671         final URL url = acquireRead(type, requestor);
    672 
    673         try {
    674             FilterInputStream input = new FilterInputStream(url.openStream()) {
    675 
    676                 private volatile boolean closed = false;
    677 
    678                 @Override
    679                 public void close() throws IOException {
    680                     try {
    681                         super.close();
    682                     } finally {
    683                         if (!closed) {
    684                             closed = true;
    685                             unlockRead(url, requestor);
    686                         }
    687                     }
    688                 }
    689 
    690             };
    691             return input;
    692         } catch (Throwable e) {
    693             unlockRead(url, requestor);
    694             if (e instanceof IOException) {
    695                 throw (IOException) e;
    696             } else if( e instanceof RuntimeException) {
    697                 throw (RuntimeException) e;
    698             } else if( e instanceof Error ) {
    699                 throw (Error) e;
    700             } else {
    701                 throw new RuntimeException(e);
    702             }
    703         }
    704     }
    705 
    706     /**
    707      * Opens a output stream for the indicated file. A write lock is requested at
    708      * the method call and released on close.
    709      *
    710      * @param type
    711      *                the type of file to open the stream to.
    712      * @param requestor
    713      *                the object requesting the stream
    714      * @return an output stream
    715      *
    716      * @throws IOException
    717      *                 if a problem occurred opening the stream.
    718      */
    719     @SuppressWarnings("resource")
    720     @Override
    721     public OutputStream getOutputStream(ShpFileType type,
    722             final FileWriter requestor) throws IOException {
    723         final URL url = acquireWrite(type, requestor);
    724 
    725         try {
    726 
    727             OutputStream out;
    728             if (isLocalTab()) {
    729                 File file = DataUtilities.urlToFile(url);
    730                 out = new FileOutputStream(file);
    731             } else {
    732                 URLConnection connection = url.openConnection();
    733                 connection.setDoOutput(true);
    734                 out = connection.getOutputStream();
    735             }
    736 
    737             FilterOutputStream output = new FilterOutputStream(out) {
    738 
    739                 private volatile boolean closed = false;
    740 
    741                 @Override
    742                 public void close() throws IOException {
    743                     try {
    744                         super.close();
    745                     } finally {
    746                         if (!closed) {
    747                             closed = true;
    748                             unlockWrite(url, requestor);
    749                         }
    750                     }
    751                 }
    752 
    753             };
    754 
    755             return output;
    756         } catch (Throwable e) {
    757             unlockWrite(url, requestor);
    758             if (e instanceof IOException) {
    759                 throw (IOException) e;
    760             } else if (e instanceof RuntimeException) {
    761                 throw (RuntimeException) e;
    762             } else if (e instanceof Error) {
    763                 throw (Error) e;
    764             } else {
    765                 throw new RuntimeException(e);
    766             }
    767         }
    768     }
    769 
    770     /**
    771      * Obtain a ReadableByteChannel from the given URL. If the url protocol is
    772      * file, a FileChannel will be returned. Otherwise a generic channel will be
    773      * obtained from the urls input stream.
    774      * <p>
    775      * A read lock is obtained when this method is called and released when the
    776      * channel is closed.
    777      * </p>
    778      *
    779      * @param type
    780      *                the type of file to open the channel to.
    781      * @param requestor
    782      *                the object requesting the channel
    783      *
    784      */
    785     @Override
    786     public ReadableByteChannel getReadChannel(ShpFileType type,
    787             FileReader requestor) throws IOException {
    788         URL url = acquireRead(type, requestor);
    789         ReadableByteChannel channel = null;
    790         try {
    791             if (isLocalTab()) {
    792 
    793                 File file = DataUtilities.urlToFile(url);
    794 
    795                 @SuppressWarnings("resource")
    796                 RandomAccessFile raf = new RandomAccessFile(file, "r");
    797                 channel = new FileChannelDecorator(raf.getChannel(), this, url,
    798                         requestor);
    799 
    800             } else {
    801                 InputStream in = url.openConnection().getInputStream();
    802                 channel = new ReadableByteChannelDecorator(Channels
    803                         .newChannel(in), this, url, requestor);
    804             }
    805         } catch (Throwable e) {
    806             unlockRead(url, requestor);
    807             if (e instanceof IOException) {
    808                 throw (IOException) e;
    809             } else if (e instanceof RuntimeException) {
    810                 throw (RuntimeException) e;
    811             } else if (e instanceof Error) {
    812                 throw (Error) e;
    813             } else {
    814                 throw new RuntimeException(e);
    815             }
    816         }
    817         return channel;
    818     }
    819 
    820     /**
    821      * Obtain a WritableByteChannel from the given URL. If the url protocol is
    822      * file, a FileChannel will be returned. Currently, this method will return
    823      * a generic channel for remote urls, however both shape and dbf writing can
    824      * only occur with a local FileChannel channel.
    825      *
    826      * <p>
    827      * A write lock is obtained when this method is called and released when the
    828      * channel is closed.
    829      * </p>
    830      *
    831      *
    832      * @param type
    833      *                the type of file to open the stream to.
    834      * @param requestor
    835      *                the object requesting the stream
    836      *
    837      * @return a WritableByteChannel for the provided file type
    838      *
    839      * @throws IOException
    840      *                 if there is an error opening the stream
    841      */
    842     @Override
    843     public WritableByteChannel getWriteChannel(ShpFileType type,
    844             FileWriter requestor) throws IOException {
    845 
    846         URL url = acquireWrite(type, requestor);
    847 
    848         try {
    849             WritableByteChannel channel;
    850             if (isLocalTab()) {
    851 
    852                 File file = DataUtilities.urlToFile(url);
    853 
    854                 @SuppressWarnings("resource")
    855                 RandomAccessFile raf = new RandomAccessFile(file, "rw");
    856                 channel = new FileChannelDecorator(raf.getChannel(), this, url,
    857                         requestor);
    858 
    859                 ((FileChannel) channel).lock();
    860 
    861             } else {
    862                 OutputStream out = url.openConnection().getOutputStream();
    863                 channel = new WritableByteChannelDecorator(Channels
    864                         .newChannel(out), this, url, requestor);
    865             }
    866 
    867             return channel;
    868         } catch (Throwable e) {
    869             unlockWrite(url, requestor);
    870             if (e instanceof IOException) {
    871                 throw (IOException) e;
    872             } else if (e instanceof RuntimeException) {
    873                 throw (RuntimeException) e;
    874             } else if (e instanceof Error) {
    875                 throw (Error) e;
    876             } else {
    877                 throw new RuntimeException(e);
    878             }
    879         }
    880     }
    881 
    882     /**
    883      * Obtains a Storage file for the type indicated. An id is provided so that
    884      * the same file can be obtained at a later time with just the id
    885      *
    886      * @param type
    887      *                the type of file to create and return
    888      *
    889      * @return StorageFile
    890      * @throws IOException
    891      *                 if temporary files cannot be created
    892      */
    893     @Override
    894     public StorageFile getStorageFile(ShpFileType type) throws IOException {
    895         String baseName = getTypeName();
    896         if (baseName.length() < 3) { // min prefix length for createTempFile
    897             baseName = baseName + "___".substring(0, 3 - baseName.length());
    898         }
    899         File tmp = File.createTempFile(baseName, type.extensionWithPeriod);
    900         return new StorageFile(this, tmp, type);
    901     }
    902 
    903     @Override
    904149    public String getTypeName() {
    905150        String path = SHP.toBase(urls.get(SHP));
     
    913158        return path.substring(slash, dot);
    914159    }
    915 
    916     /**
    917      * Internal method that the file channel decorators will call to allow reuse of the memory mapped buffers
    918      * @param wrapped
    919      * @param url
    920      * @param mode
    921      * @param position
    922      * @param size
    923      * @return
    924      * @throws IOException
    925      */
    926     @Override
    927     MappedByteBuffer map(FileChannel wrapped, URL url, MapMode mode, long position, long size) throws IOException {
    928         if(memoryMapCacheEnabled) {
    929             return mapCache.map(wrapped, url, mode, position, size);
    930         } else {
    931             return wrapped.map(mode, position, size);
    932         }
    933     }
    934 
    935     /**
    936      * Returns the status of the memory map cache. When enabled the memory mapped portions of the files are cached and shared
    937      * (giving each thread a clone of it)
    938      * @param memoryMapCacheEnabled
    939      */
    940     @Override
    941     public boolean isMemoryMapCacheEnabled() {
    942         return memoryMapCacheEnabled;
    943     }
    944 
    945     /**
    946      * Enables the memory map cache. When enabled the memory mapped portions of the files are cached and shared
    947      * (giving each thread a clone of it)
    948      * @param memoryMapCacheEnabled
    949      */
    950     @Override
    951     public void setMemoryMapCacheEnabled(boolean memoryMapCacheEnabled) {
    952         this.memoryMapCacheEnabled = memoryMapCacheEnabled;
    953         if (!memoryMapCacheEnabled) {
    954             mapCache.clean();
    955         }
    956     }
    957 
    958     /**
    959      * Returns true if the file exists. Throws an exception if the file is not
    960      * local.
    961      *
    962      * @param fileType
    963      *                the type of file to check existance for.
    964      *
    965      * @return true if the file exists.
    966      *
    967      * @throws IllegalArgumentException
    968      *                 if the files are not local.
    969      */
    970     public boolean existsTab(ShpFileType fileType) throws IllegalArgumentException {
    971         if (!isLocalTab()) {
    972             throw new IllegalArgumentException(
    973                     "This method only makes sense if the files are local");
    974         }
    975         URL url = urls.get(fileType);
    976         if (url == null) {
    977             return false;
    978         }
    979 
    980         File file = DataUtilities.urlToFile(url);
    981         return file.exists();
    982     }
    983160}
  • applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/geographic/TabReader.java

    r33518 r33613  
    1515import org.geotools.data.shapefile.dbf.DbaseFileReader;
    1616import org.geotools.data.shapefile.dbf.DbaseFileReader.Row;
    17 import org.geotools.data.shapefile.files.TabFiles;
    1817import org.openstreetmap.josm.data.osm.DataSet;
    1918import org.openstreetmap.josm.gui.progress.ProgressMonitor;
Note: See TracChangeset for help on using the changeset viewer.