Example usage for java.lang SecurityException SecurityException

List of usage examples for java.lang SecurityException SecurityException

Introduction

In this page you can find the example usage for java.lang SecurityException SecurityException.

Prototype

public SecurityException(Throwable cause) 

Source Link

Document

Creates a SecurityException with the specified cause and a detail message of (cause==null ?

Usage

From source file:it.scoppelletti.programmerpower.security.CryptoUtils.java

/**
 * Restituisce i parametri per la ricostruzione di una chiave di
 * crittografia./*from   w w  w .  j  a  va  2s  .co m*/
 * 
 * <P>Il metodo {@code toProperties} rileva i provider del servizio
 * {@code KeyToPropertySetProvider} disponibili e delega il calcolo dei
 * parametri al primo di questi che supporta la tipologia della chiave di
 * crittografia {@code key}; se nessuno dei provider supporta la specifica
 * tipologia di chiavi, restituisce i parametri che rappresentano la chiave
 * codificata come sequenza di byte nel formato Base64 come definito da RFC
 * 2045.</P>
 * 
 * @param  key     Chiave.
 * @param  encoded Indica se restituire i parametri che rappresentano la
 *                 chiave codificata come sequenza di byte senza rilevare
 *                 gli eventuali provider {@code KeyToPropertySetProvider}
 *                 disponibili.
 * @return         Propriet&agrave;. 
 * @see #getKey
 * @see it.scoppelletti.programmerpower.security.spi.CryptoKeyFactory
 * @see it.scoppelletti.programmerpower.security.spi.EncodedKeyFactory
 * @see it.scoppelletti.programmerpower.security.spi.KeyToPropertySetProvider
 * @see <A HREF="http://www.ietf.org/rfc/rfc2045.txt" TARGET="_blank">RFC
 *      2045: Multipurpose Internet Mail Extensions (MIME) Part One: Format
 *      of Internet Message Bodies</A> 
 */
public static Properties toProperties(Key key, boolean encoded) {
    byte[] data;
    KeyRep.Type keyType;
    Properties props;
    KeyToPropertySetService svc;
    SecurityResources res = new SecurityResources();

    if (key == null) {
        throw new ArgumentNullException("key");
    }

    if (!encoded) {
        svc = new KeyToPropertySetService(key);
        props = svc.query();
        if (props != null) {
            return props;
        }
    }

    if (key instanceof PublicKey) {
        keyType = KeyRep.Type.PUBLIC;
    } else if (key instanceof PrivateKey) {
        keyType = KeyRep.Type.PRIVATE;
    } else if (key instanceof SecretKey) {
        keyType = KeyRep.Type.SECRET;
    } else {
        throw new InvalidCastException(key.getClass().getName(), KeyRep.Type.class.getName());
    }

    data = key.getEncoded();
    if (data == null) {
        throw new SecurityException(res.getEncodedFormatNotSupportedException());
    }

    props = new Properties();
    if (keyType == KeyRep.Type.SECRET) {
        props.setProperty(CryptoUtils.PROP_KEYFACTORY, RawKeyFactory.class.getName());
    } else {
        props.setProperty(CryptoUtils.PROP_KEYFACTORY, EncodedKeyFactory.class.getName());
        props.setProperty(EncodedKeyFactory.PROP_KEYTYPE, keyType.name());
    }

    props.setProperty(RawKeyFactory.PROP_ALGORITHM, key.getAlgorithm());
    props.setProperty(RawKeyFactory.PROP_DATA, Base64.encodeBase64String(data));

    return props;
}

From source file:org.apache.catalina.core.StandardWrapper.java

/**
 * Load and initialize an instance of this servlet, if there is not already
 * at least one initialized instance.  This can be used, for example, to
 * load servlets that are marked in the deployment descriptor to be loaded
 * at server startup time./* w  w w.  ja  va2s  .  com*/
 */
public synchronized Servlet loadServlet() throws ServletException {

    // Nothing to do if we already have an instance or an instance pool
    if (!singleThreadModel && (instance != null))
        return instance;

    PrintStream out = System.out;
    if (swallowOutput) {
        SystemLogHandler.startCapture();
    }

    Servlet servlet;
    try {
        long t1 = System.currentTimeMillis();
        // If this "servlet" is really a JSP file, get the right class.
        // HOLD YOUR NOSE - this is a kludge that avoids having to do special
        // case Catalina-specific code in Jasper - it also requires that the
        // servlet path be replaced by the <jsp-file> element content in
        // order to be completely effective
        String actualClass = servletClass;
        if ((actualClass == null) && (jspFile != null)) {
            Wrapper jspWrapper = (Wrapper) ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
            if (jspWrapper != null)
                actualClass = jspWrapper.getServletClass();
        }

        // Complain if no servlet class has been specified
        if (actualClass == null) {
            unavailable(null);
            throw new ServletException(sm.getString("standardWrapper.notClass", getName()));
        }

        // Acquire an instance of the class loader to be used
        Loader loader = getLoader();
        if (loader == null) {
            unavailable(null);
            throw new ServletException(sm.getString("standardWrapper.missingLoader", getName()));
        }

        ClassLoader classLoader = loader.getClassLoader();

        // Special case class loader for a container provided servlet
        //  
        if (isContainerProvidedServlet(actualClass) && !((Context) getParent()).getPrivileged()) {
            // If it is a priviledged context - using its own
            // class loader will work, since it's a child of the container
            // loader
            classLoader = this.getClass().getClassLoader();
        }

        // Load the specified servlet class from the appropriate class loader
        Class classClass = null;
        try {
            if (System.getSecurityManager() != null) {
                final ClassLoader fclassLoader = classLoader;
                final String factualClass = actualClass;
                try {
                    classClass = (Class) AccessController.doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws Exception {
                            if (fclassLoader != null) {
                                return fclassLoader.loadClass(factualClass);
                            } else {
                                return Class.forName(factualClass);
                            }
                        }
                    });
                } catch (PrivilegedActionException pax) {
                    Exception ex = pax.getException();
                    if (ex instanceof ClassNotFoundException) {
                        throw (ClassNotFoundException) ex;
                    } else {
                        getServletContext().log("Error loading " + fclassLoader + " " + factualClass, ex);
                    }
                }
            } else {
                if (classLoader != null) {
                    classClass = classLoader.loadClass(actualClass);
                } else {
                    classClass = Class.forName(actualClass);
                }
            }
        } catch (ClassNotFoundException e) {
            unavailable(null);

            getServletContext().log("Error loading " + classLoader + " " + actualClass, e);
            throw new ServletException(sm.getString("standardWrapper.missingClass", actualClass), e);
        }

        if (classClass == null) {
            unavailable(null);
            throw new ServletException(sm.getString("standardWrapper.missingClass", actualClass));
        }

        // Instantiate and initialize an instance of the servlet class itself
        try {
            servlet = (Servlet) classClass.newInstance();
        } catch (ClassCastException e) {
            unavailable(null);
            // Restore the context ClassLoader
            throw new ServletException(sm.getString("standardWrapper.notServlet", actualClass), e);
        } catch (Throwable e) {
            unavailable(null);
            // Restore the context ClassLoader
            throw new ServletException(sm.getString("standardWrapper.instantiate", actualClass), e);
        }

        // Check if loading the servlet in this web application should be
        // allowed
        if (!isServletAllowed(servlet)) {
            throw new SecurityException(sm.getString("standardWrapper.privilegedServlet", actualClass));
        }

        // Special handling for ContainerServlet instances
        if ((servlet instanceof ContainerServlet)
                && (isContainerProvidedServlet(actualClass) || ((Context) getParent()).getPrivileged())) {
            ((ContainerServlet) servlet).setWrapper(this);
        }

        classLoadTime = (int) (System.currentTimeMillis() - t1);
        // Call the initialization method of this servlet
        try {
            instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, servlet);

            if (System.getSecurityManager() != null) {
                Class[] classType = new Class[] { ServletConfig.class };
                Object[] args = new Object[] { ((ServletConfig) facade) };
                SecurityUtil.doAsPrivilege("init", servlet, classType, args);
            } else {
                servlet.init(facade);
            }

            // Invoke jspInit on JSP pages
            if ((loadOnStartup >= 0) && (jspFile != null)) {
                // Invoking jspInit
                DummyRequest req = new DummyRequest();
                req.setServletPath(jspFile);
                req.setQueryString("jsp_precompile=true");
                DummyResponse res = new DummyResponse();

                if (System.getSecurityManager() != null) {
                    Class[] classType = new Class[] { ServletRequest.class, ServletResponse.class };
                    Object[] args = new Object[] { req, res };
                    SecurityUtil.doAsPrivilege("service", servlet, classType, args);
                } else {
                    servlet.service(req, res);
                }
            }
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet);
        } catch (UnavailableException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);
            unavailable(f);
            throw f;
        } catch (ServletException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw f;
        } catch (Throwable f) {
            getServletContext().log("StandardWrapper.Throwable", f);
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw new ServletException(sm.getString("standardWrapper.initException", getName()), f);
        }

        // Register our newly initialized instance
        singleThreadModel = servlet instanceof SingleThreadModel;
        if (singleThreadModel) {
            if (instancePool == null)
                instancePool = new Stack();
        }
        fireContainerEvent("load", this);

        loadTime = System.currentTimeMillis() - t1;
    } finally {
        if (swallowOutput) {
            String log = SystemLogHandler.stopCapture();
            if (log != null && log.length() > 0) {
                if (getServletContext() != null) {
                    getServletContext().log(log);
                } else {
                    out.println(log);
                }
            }
        }
    }
    return servlet;

}

From source file:eu.trentorise.smartcampus.permissionprovider.manager.ResourceManager.java

/**
 * Save the specified {@link ServiceDescriptor} object, only the id/name/description fields
 * @param service// w w w . jav a2  s  . c o  m
 * @param userId
 * @return
 */
public Service saveServiceObject(Service service, Long userId) {
    validateServiceData(service);
    ServiceDescriptor sdOld = serviceRepository.findOne(service.getId());
    if (sdOld != null && !sdOld.getOwnerId().equals(userId.toString())) {
        throw new SecurityException("Service ID is in use by another user");
    }
    ServiceDescriptor sd = sdOld == null ? Utils.toServiceEntity(service) : sdOld;
    sd.setDescription(service.getDescription());
    sd.setServiceName(service.getName());
    sd.setServiceId(service.getId());
    sd.setOwnerId(userId.toString());
    sd = serviceRepository.save(sd);
    return Utils.toServiceObject(sd);
}

From source file:org.csploit.android.core.UpdateService.java

/**
 * check if mLocalFile exists./*from   w w w. j av  a  2s .  c o  m*/
 *
 * @return true if file exists and match md5sum and sha1sum.
 * @throws java.util.concurrent.CancellationException when check is cancelled by user
 * @throws SecurityException bad file permissions
 * @throws IOException when IOException occurs
 * @throws java.security.NoSuchAlgorithmException when digests cannot be created
 * @throws java.security.KeyException when file checksum fails
 */
private boolean haveLocalFile()
        throws CancellationException, SecurityException, IOException, NoSuchAlgorithmException, KeyException {

    File file = null;
    InputStream reader = null;
    boolean exitForError = true;

    if (mCurrentTask.path == null)
        return false;

    try {
        MessageDigest md5, sha1;
        byte[] buffer;
        int read;
        short percentage, previous_percentage;
        long read_counter, total;

        file = new File(mCurrentTask.path);
        buffer = new byte[4096];
        total = file.length();
        read_counter = 0;
        previous_percentage = -1;

        if (!file.exists() || !file.isFile())
            return false;

        if (!file.canWrite() || !file.canRead()) {
            read = -1;
            try {
                read = System.getTools().raw.run(String.format("chmod 777 '%s'", mCurrentTask.path));
            } catch (Exception e) {
                System.errorLogging(e);
            }
            if (read != 0)
                throw new SecurityException(String.format("bad file permissions for '%s', chmod returned: %d",
                        mCurrentTask.path, read));
        }

        if (mCurrentTask.md5 != null || mCurrentTask.sha1 != null) {
            mBuilder.setContentTitle(getString(R.string.checking))
                    .setSmallIcon(android.R.drawable.ic_popup_sync).setContentText("")
                    .setProgress(100, 0, false);
            mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

            md5 = (mCurrentTask.md5 != null ? MessageDigest.getInstance("MD5") : null);
            sha1 = (mCurrentTask.sha1 != null ? MessageDigest.getInstance("SHA-1") : null);

            reader = new FileInputStream(file);
            while (mRunning && (read = reader.read(buffer)) != -1) {
                if (md5 != null)
                    md5.update(buffer, 0, read);
                if (sha1 != null)
                    sha1.update(buffer, 0, read);

                read_counter += read;

                percentage = (short) (((double) read_counter / total) * 100);
                if (percentage != previous_percentage) {
                    mBuilder.setProgress(100, percentage, false).setContentInfo(percentage + "%");
                    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                    previous_percentage = percentage;
                }
            }
            reader.close();
            reader = null;
            if (!mRunning) {
                exitForError = false;
                throw new CancellationException("local file check cancelled");
            }
            if (md5 != null && !mCurrentTask.md5.equals(digest2string(md5.digest())))
                throw new KeyException("wrong MD5");
            if (sha1 != null && !mCurrentTask.sha1.equals(digest2string(sha1.digest())))
                throw new KeyException("wrong SHA-1");
            Logger.info(String.format("checksum ok: '%s'", mCurrentTask.path));
        } else if (mCurrentTask.archiver != null) {
            verifyArchiveIntegrity();
        }
        Logger.info(String.format("file already exists: '%s'", mCurrentTask.path));
        mBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done)
                .setContentTitle(getString(R.string.update_available))
                .setContentText(getString(R.string.click_here_to_upgrade)).setProgress(0, 0, false) // remove progress bar
                .setAutoCancel(true);
        exitForError = false;
        return true;
    } finally {
        if (exitForError && file != null && file.exists() && !file.delete())
            Logger.error(String.format("cannot delete local file '%s'", mCurrentTask.path));
        try {
            if (reader != null)
                reader.close();
        } catch (IOException e) {
            System.errorLogging(e);
        }
    }
}

From source file:org.callistasoftware.netcare.core.spi.impl.HealthPlanServiceImpl.java

protected ServiceResult<ScheduledActivity> createOrUpdateCommentOnPerformedActivity(Long activityId,
        String comment, Boolean like, Boolean hasBeenRead) {
    final ScheduledActivityEntity ent = this.scheduledActivityRepository.findOne(activityId);
    if (ent == null) {
        return ServiceResultImpl
                .createFailedResult(new EntityNotFoundMessage(ScheduledActivityEntity.class, activityId));
    }/*from   w ww. j a v  a 2  s .  c o m*/

    this.verifyWriteAccess(ent);

    final UserEntity user = this.getCurrentUser();
    if (user.isCareActor()) {
        final CareActorEntity ca = (CareActorEntity) user;

        ActivityCommentEntity commentEntity = null;
        if (ent.getComments().size() > 0) {
            commentEntity = ent.getComments().get(0);
        } else {
            commentEntity = ActivityCommentEntity.newEntity("", ca, ent);
            ent.getComments().add(commentEntity);
        }

        if (StringUtils.hasText(comment)) {
            commentEntity.setComment(comment);
        } else if (like != null) {
            commentEntity.setLike(like);
        } else if (hasBeenRead != null) {
            commentEntity.setMarkedAsRead(hasBeenRead);
        }

        return ServiceResultImpl.createSuccessResult(ScheduledActivityImpl.newFromEntity(ent),
                new GenericSuccessMessage());
    } else {
        throw new SecurityException("A patient is not allow to comment his own activity");
    }
}

From source file:org.sakaiproject.iclicker.logic.IClickerLogic.java

/**
 * ADMIN ONLY/*from  ww w  .  j  av a2  s  .c  o m*/
 * Only the admin can use this method to retrieve all clicker IDs
 * @param first the first item (for paging and limiting)
 * @param max the max number of items to return
 * @param order [OPTIONAL] sort order for the items
 * @param searchStr [OPTIONAL] search by partial clickerId
 * @param includeUserDisplayNames if true the user display names are added to the results
 * @return a list of clicker registrations
 */
public List<ClickerRegistration> getAllItems(int first, int max, String order, String searchStr,
        boolean includeUserDisplayNames) {
    // admin only
    if (!externalLogic.isUserAdmin(externalLogic.getCurrentUserId())) {
        throw new SecurityException("Only admins can get the listing of all clicker registrations");
    }
    if (order == null || "".equals(order)) {
        order = "clickerId";
    }
    Search s = new Search();
    s.setStart(first);
    s.setLimit(max);
    s.addOrder(new Order(order));
    if (searchStr != null && !"".equals(searchStr)) {
        // maybe allow search on more than clickerId later
        s.addRestriction(new Restriction("clickerId", searchStr, Restriction.LIKE));
    }
    List<ClickerRegistration> l = dao.findBySearch(ClickerRegistration.class, s);
    // optionally include the user names
    if (includeUserDisplayNames) {
        for (ClickerRegistration reg : l) {
            reg.userDisplayName = getUserDisplayName(reg.getOwnerId());
        }
    }
    return l;
}

From source file:com.amazonaws.services.kinesis.producer.KinesisProducer.java

private void extractBinaries() {
    synchronized (EXTRACT_BIN_MUTEX) {
        final List<File> watchFiles = new ArrayList<>(2);
        String os = SystemUtils.OS_NAME;
        if (SystemUtils.IS_OS_WINDOWS) {
            os = "windows";
        } else if (SystemUtils.IS_OS_LINUX) {
            os = "linux";
        } else if (SystemUtils.IS_OS_MAC_OSX) {
            os = "osx";
        } else {/*from  w w  w. ja  va  2 s  .  c o m*/
            throw new RuntimeException("Your operation system is not supported (" + os
                    + "), the KPL only supports Linux, OSX and Windows");
        }

        String root = "amazon-kinesis-producer-native-binaries";
        String tmpDir = config.getTempDirectory();
        if (tmpDir.trim().length() == 0) {
            tmpDir = System.getProperty("java.io.tmpdir");
        }
        tmpDir = Paths.get(tmpDir, root).toString();
        pathToTmpDir = tmpDir;

        String binPath = config.getNativeExecutable();
        if (binPath != null && !binPath.trim().isEmpty()) {
            pathToExecutable = binPath.trim();
            log.warn("Using non-default native binary at " + pathToExecutable);
            pathToLibDir = "";
        } else {
            log.info("Extracting binaries to " + tmpDir);
            try {
                File tmpDirFile = new File(tmpDir);
                if (!tmpDirFile.exists() && !tmpDirFile.mkdirs()) {
                    throw new IOException("Could not create tmp dir " + tmpDir);
                }

                String extension = os.equals("windows") ? ".exe" : "";
                String executableName = "kinesis_producer" + extension;
                byte[] bin = IOUtils.toByteArray(this.getClass().getClassLoader()
                        .getResourceAsStream(root + "/" + os + "/" + executableName));
                MessageDigest md = MessageDigest.getInstance("SHA1");
                String mdHex = DatatypeConverter.printHexBinary(md.digest(bin)).toLowerCase();

                pathToExecutable = Paths.get(pathToTmpDir, "kinesis_producer_" + mdHex + extension).toString();
                File extracted = new File(pathToExecutable);
                watchFiles.add(extracted);
                if (extracted.exists()) {
                    try (FileInputStream fis = new FileInputStream(extracted);
                            FileLock lock = fis.getChannel().lock(0, Long.MAX_VALUE, true)) {
                        boolean contentEqual = false;
                        if (extracted.length() == bin.length) {
                            byte[] existingBin = IOUtils.toByteArray(new FileInputStream(extracted));
                            contentEqual = Arrays.equals(bin, existingBin);
                        }
                        if (!contentEqual) {
                            throw new SecurityException("The contents of the binary "
                                    + extracted.getAbsolutePath() + " is not what it's expected to be.");
                        }
                    }
                } else {
                    try (FileOutputStream fos = new FileOutputStream(extracted);
                            FileLock lock = fos.getChannel().lock()) {
                        IOUtils.write(bin, fos);
                    }
                    extracted.setExecutable(true);
                }

                String certFileName = "b204d74a.0";
                File certFile = new File(pathToTmpDir, certFileName);
                if (!certFile.exists()) {
                    try (FileOutputStream fos = new FileOutputStream(certFile);
                            FileLock lock = fos.getChannel().lock()) {
                        byte[] certs = IOUtils.toByteArray(this.getClass().getClassLoader()
                                .getResourceAsStream("cacerts/" + certFileName));
                        IOUtils.write(certs, fos);
                    }
                }

                watchFiles.add(certFile);
                pathToLibDir = pathToTmpDir;
                FileAgeManager.instance().registerFiles(watchFiles);
            } catch (Exception e) {
                throw new RuntimeException("Could not copy native binaries to temp directory " + tmpDir, e);
            }

        }
    }
}

From source file:de.juwimm.cms.remote.UserServiceSpringImpl.java

/**
 * Remove a Task from the TaskQueue<br>
 * <b>SECURITY INFORMATION:</b> You only can remove Tasks, if you're the
 * sender, the receiver, <i>siteRoot</i> or in the receiver group.
 * /*  ww  w.  jav a 2s . c o m*/
 * @param taskId
 *            The TaskId to remove
 * 
 * @see de.juwimm.cms.remote.UserServiceSpring#removeTask(java.lang.Integer)
 */
@Override
protected void handleRemoveTask(Integer taskId) throws Exception {
    TaskHbm task = null;
    task = super.getTaskHbmDao().load(taskId);
    if (task != null) {
        UserHbm user = null;
        try {
            user = super.getUserHbmDao().load(AuthenticationHelper.getUserName());
        } catch (Exception exe) {
            log.error("Error thrown while returning logged in user: " + exe.getMessage());
            // context.setRollbackOnly();
            throw new UserException("Can't find the actual logged in user. Check the logs and retry");
        }
        if (!!getUserHbmDao().isInRole(user, UserRights.SITE_ROOT, user.getActiveSite())
                && !user.equals(task.getReceiver()) && !user.equals(task.getSender())
                && !!getUserHbmDao().isInRole(user, task.getReceiverRole(), user.getActiveSite())) {
            // context.setRollbackOnly();
            throw new SecurityException("User is not responsible to delete this Task. RECEIVER:"
                    + task.getReceiver().getUserId() + " SENDER:" + task.getSender().getUserId()
                    + " RECEIVERROLE:" + task.getReceiverRole() + " THIS USER:" + user.getUserId());
        }
        try {
            super.getTaskHbmDao().remove(task);
        } catch (Exception e) {
            throw new UserException(e.getMessage());
        }
    }
}

From source file:com.csipsimple.db.DBProvider.java

private static void checkSelection(List<String> possibles, String selection) {
    if (selection != null) {
        String cleanSelection = selection.toLowerCase();
        for (String field : possibles) {
            cleanSelection = cleanSelection.replace(field, "");
        }/*from w ww .j  a v a  2  s.co m*/
        cleanSelection = cleanSelection.replaceAll(" in \\([0-9 ,]+\\)", "");
        cleanSelection = cleanSelection.replaceAll(" and ", "");
        cleanSelection = cleanSelection.replaceAll(" or ", "");
        cleanSelection = cleanSelection.replaceAll("[0-9]+", "");
        cleanSelection = cleanSelection.replaceAll("[=? ]", "");
        if (cleanSelection.length() > 0) {
            throw new SecurityException("You are selecting wrong thing " + cleanSelection);
        }
    }
}

From source file:com.csipsimple.db.DBProvider.java

private static void checkProjection(List<String> possibles, String[] projection) {
    if (projection != null) {
        // Ensure projection is valid
        for (String proj : projection) {
            proj = proj.replaceAll(" AS [a-zA-Z0-9_]+$", "");
            if (!possibles.contains(proj)) {
                throw new SecurityException("You are asking wrong values " + proj);
            }/*from  ww  w. j av a 2 s.co  m*/
        }
    }
}