类org.apache.logging.log4j.core.config.DefaultConfiguration源码实例Demo

下面列出了怎么用org.apache.logging.log4j.core.config.DefaultConfiguration的API类实例代码及写法,或者点击链接到github查看源代码。

源代码1 项目: sofa-common-tools   文件: Log4j2IntegrationTest.java
/**
 * test log4j2 root level config
 */
@Test
public void testRootLevelConfig() {
    SPACES_MAP.remove(new SpaceId(TEST_SPACE));
    System.setProperty(DefaultConfiguration.DEFAULT_LEVEL, "ERROR");

    logger = LoggerSpaceManager.getLoggerBySpace(
        LogbackIntegrationTest.class.getCanonicalName(), TEST_SPACE);

    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put(
        String.format(Constants.SOFA_MIDDLEWARE_SINGLE_LOG_CONSOLE_SWITCH, TEST_SPACE), "true");
    SpringApplication springApplication = new SpringApplication(
        LogbackIntegrationTest.EmptyConfig.class);
    springApplication.setDefaultProperties(properties);
    springApplication.run(new String[] {});

    logger.info("space info console");
    logger.error("space error console");
    Assert.assertFalse(outContent.toString().contains("space info console"));
    Assert.assertTrue(outContent.toString().contains("space error console"));

    System.getProperties().remove(DefaultConfiguration.DEFAULT_LEVEL);
    LogEnvUtils.processGlobalSystemLogProperties().remove(
        String.format(Constants.SOFA_MIDDLEWARE_SINGLE_LOG_CONSOLE_SWITCH, TEST_SPACE));
}
 
源代码2 项目: curiostack   文件: StackdriverJsonLayout.java
/**
 * Creates a JSON Layout using the default settings. Useful for testing.
 *
 * @return A JSON Layout.
 */
public static StackdriverJsonLayout createDefaultLayout() {
  return new StackdriverJsonLayout(
      new DefaultConfiguration(),
      false,
      false,
      false,
      false,
      false,
      false,
      DEFAULT_HEADER,
      DEFAULT_FOOTER,
      StandardCharsets.UTF_8,
      true,
      false,
      false,
      null,
      false);
}
 
源代码3 项目: logging-log4j2   文件: JdbcAppenderBenchmark.java
@Setup
public void setup() throws Exception {
    connectionHSQLDB = getConnectionHSQLDB();
    connectionH2 = getConnectionH2();
    createTable(connectionHSQLDB, toCreateTableSqlStringHQLDB("fmLogEntry"));
    createTable(connectionH2, toCreateTableSqlStringH2("fmLogEntry"));

    System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "log4j2-jdbc-appender.xml");
    final LoggerContext context = LoggerContext.getContext(false);
    if (context.getConfiguration() instanceof DefaultConfiguration) {
        context.reconfigure();
    }
    StatusLogger.getLogger().reset();
    loggerH2 = LogManager.getLogger("H2Logger");
    loggerHSQLDB = LogManager.getLogger("HSQLDBLogger");
}
 
源代码4 项目: logging-log4j2   文件: SimplePerfTest.java
@BeforeClass
  public static void setupClass() {

final Configuration config = LoggerContext.getContext().getConfiguration();

if (!DefaultConfiguration.DEFAULT_NAME.equals(config.getName())) {
	System.out.println("Configuration was " + config.getName());
	LoggerContext.getContext().start(new DefaultConfiguration());
}

      for (int i=0; i < WARMUP; ++i) {
          overhead();
      }
      System.gc();
      final Timer timer = new Timer("Setup", LOOP_CNT);
      timer.start();
      for (int i=0; i < (LOOP_CNT / 150); ++i) {
          overhead();
      }
      timer.stop();
      maxTime = timer.getElapsedNanoTime();
      System.gc();
      System.out.println(timer.toString());
  }
 
源代码5 项目: logging-log4j2   文件: ScriptConditionTest.java
@Test
public void testSelectFilesToDelete2() {
    final Configuration config = new DefaultConfiguration();
    config.initialize(); // creates the ScriptManager

    final List<PathWithAttributes> pathList = new ArrayList<>();
    pathList.add(new PathWithAttributes(Paths.get("/path/1"), new DummyFileAttributes()));
    pathList.add(new PathWithAttributes(Paths.get("/path/2"), new DummyFileAttributes()));
    pathList.add(new PathWithAttributes(Paths.get("/path/3"), new DummyFileAttributes()));

    final String scriptText = "pathList.remove(1);" //
            + "pathList;";
    final Script script = new Script("test", "javascript", scriptText);
    final ScriptCondition condition = new ScriptCondition(script, config);
    final Path base = Paths.get("baseDirectory");
    final List<PathWithAttributes> result = condition.selectFilesToDelete(base, pathList);
    assertSame(result, pathList);
    assertEquals(2, result.size());
    assertEquals(Paths.get("/path/1"), result.get(0).getPath());
    assertEquals(Paths.get("/path/3"), result.get(1).getPath());
}
 
源代码6 项目: logging-log4j2   文件: JpaAppenderBenchmark.java
@Setup
public void setup() throws Exception {
    connectionHSQLDB = getConnectionHSQLDB();
    connectionH2 = getConnectionH2();

    System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "log4j2-jpa-appender.xml");
    final LoggerContext context = LoggerContext.getContext(false);
    if (context.getConfiguration() instanceof DefaultConfiguration) {
        context.reconfigure();
    }
    StatusLogger.getLogger().reset();
    loggerH2 = LogManager.getLogger("H2Logger");
    loggerHSQLDB = LogManager.getLogger("HSQLDBLogger");
}
 
源代码7 项目: logging-log4j2   文件: SimpleBenchmark.java
@Setup
public void setup() {
    final Configuration config = (LoggerContext.getContext()).getConfiguration();
    if (!DefaultConfiguration.DEFAULT_NAME.equals(config.getName())) {
        System.out.println("Configuration was " + config.getName());
        (LoggerContext.getContext()).start(new DefaultConfiguration());
    }
    logger = LogManager.getLogger(SimpleBenchmark.class.getName());
}
 
源代码8 项目: logging-log4j2   文件: SmtpAppender.java
/**
 * Create a SmtpAppender.
 * @deprecated Use {@link #newBuilder()} to create and configure a {@link Builder} instance.
 * @see Builder
 */
public static SmtpAppender createAppender(final Configuration config, final String name, final String to,
                                          final String cc, final String bcc, final String from,
                                          final String replyTo, final String subject, final String smtpProtocol,
                                          final String smtpHost, final String smtpPortStr,
                                          final String smtpUsername, final String smtpPassword,
                                          final String smtpDebug, final String bufferSizeStr,
                                          Layout<? extends Serializable> layout, Filter filter,
                                          final String ignore) {
    if (name == null) {
        LOGGER.error("No name provided for SmtpAppender");
        return null;
    }

    final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
    final int smtpPort = AbstractAppender.parseInt(smtpPortStr, 0);
    final boolean isSmtpDebug = Boolean.parseBoolean(smtpDebug);
    final int bufferSize = bufferSizeStr == null ? DEFAULT_BUFFER_SIZE : Integer.parseInt(bufferSizeStr);

    if (layout == null) {
        layout = HtmlLayout.createDefaultLayout();
    }
    if (filter == null) {
        filter = ThresholdFilter.createFilter(null, null, null);
    }
    final Configuration configuration = config != null ? config : new DefaultConfiguration();

    final SmtpManager manager = SmtpManager.getSmtpManager(configuration, to, cc, bcc, from, replyTo, subject, smtpProtocol,
        smtpHost, smtpPort, smtpUsername, smtpPassword, isSmtpDebug, filter.toString(),  bufferSize, null);
    if (manager == null) {
        return null;
    }

    return new SmtpAppender(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY, manager);
}
 
private static JsonTemplateLayout createLayout() {
    final Configuration config = new DefaultConfiguration();
    return JsonTemplateLayout
            .newBuilder()
            .setConfiguration(config)
            .setEventTemplate("{\"message\": \"${json:message}\"}")
            .setStackTraceEnabled(false)
            .setLocationInfoEnabled(false)
            .build();
}
 
源代码10 项目: logging-log4j2   文件: AbstractJpaAppenderTest.java
public void setUp(final String configFileName) throws SQLException {
    this.connection = this.setUpConnection();

    final String resource = "org/apache/logging/log4j/jpa/appender/" + configFileName;
    assertNotNull(getClass().getClassLoader().getResource(resource));
    System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
            resource);
    PropertiesUtil.getProperties().reload();
    final LoggerContext context = LoggerContext.getContext(false);
    if (context.getConfiguration() instanceof DefaultConfiguration) {
        context.reconfigure();
    }
    StatusLogger.getLogger().reset();
}
 
源代码11 项目: logging-log4j2   文件: AsyncLoggerContext.java
private void maybeStartHelper(final Configuration config) {
    // If no log4j configuration was found, there are no loggers
    // and there is no point in starting the disruptor (which takes up
    // significant memory and starts a thread).
    if (config instanceof DefaultConfiguration) {
        StatusLogger.getLogger().debug("[{}] Not starting Disruptor for DefaultConfiguration.", getName());
    } else {
        loggerDisruptor.start();
    }
}
 
源代码12 项目: logging-log4j2   文件: LateConfigTest.java
@Test
public void testReconfiguration() throws Exception {
    final Configuration cfg = context.getConfiguration();
    assertNotNull("No configuration", cfg);
    assertTrue("Not set to default configuration", cfg instanceof DefaultConfiguration);
    final File file = new File(CONFIG);
    final LoggerContext loggerContext = LoggerContext.getContext(null, false, file.toURI());
    assertNotNull("No Logger Context", loggerContext);
    final Configuration newConfig = loggerContext.getConfiguration();
    assertTrue("Configuration not reset", cfg != newConfig);
    assertTrue("Reconfiguration failed", newConfig instanceof XmlConfiguration);
    context = LoggerContext.getContext(false);
    final Configuration sameConfig = context.getConfiguration();
    assertTrue("Configuration should not have been reset", newConfig == sameConfig);
}
 
源代码13 项目: logging-log4j2   文件: WatchHttpTest.java
@Test
public void testWatchManager() throws Exception {
    BlockingQueue<String> queue = new LinkedBlockingQueue<>();
    List<ConfigurationListener> listeners = new ArrayList<>();
    listeners.add(new TestConfigurationListener(queue, "log4j-test1.xml"));
    TimeZone timeZone = TimeZone.getTimeZone("UTC");
    Calendar now = Calendar.getInstance(timeZone);
    Calendar previous = now;
    previous.add(Calendar.MINUTE, -5);
    Configuration configuration = new DefaultConfiguration();
    Assume.assumeTrue(!IS_WINDOWS || Boolean.getBoolean(FORCE_RUN_KEY));
    URL url = new URL("http://localhost:" + wireMockRule.port() + "/log4j-test1.xml");
    StubMapping stubMapping = stubFor(get(urlPathEqualTo("/log4j-test1.xml"))
        .willReturn(aResponse()
        .withBodyFile(file)
        .withStatus(200)
        .withHeader("Last-Modified", formatter.format(previous) + " GMT")
        .withHeader("Content-Type", XML)));
    final ConfigurationScheduler scheduler = new ConfigurationScheduler();
    scheduler.incrementScheduledItems();
    final WatchManager watchManager = new WatchManager(scheduler);
    watchManager.setIntervalSeconds(1);
    scheduler.start();
    watchManager.start();
    try {
        watchManager.watch(new Source(url.toURI(), previous.getTimeInMillis()), new HttpWatcher(configuration, null,
            listeners, previous.getTimeInMillis()));
        final String str = queue.poll(2, TimeUnit.SECONDS);
        assertNotNull("File change not detected", str);
    } finally {
        removeStub(stubMapping);
        watchManager.stop();
        scheduler.stop();
    }
}
 
源代码14 项目: logging-log4j2   文件: WatchHttpTest.java
@Test
public void testNotModified() throws Exception {
    BlockingQueue<String> queue = new LinkedBlockingQueue<>();
    List<ConfigurationListener> listeners = new ArrayList<>();
    listeners.add(new TestConfigurationListener(queue, "log4j-test2.xml"));
    TimeZone timeZone = TimeZone.getTimeZone("UTC");
    Calendar now = Calendar.getInstance(timeZone);
    Calendar previous = now;
    previous.add(Calendar.MINUTE, -5);
    Configuration configuration = new DefaultConfiguration();
    Assume.assumeTrue(!IS_WINDOWS || Boolean.getBoolean(FORCE_RUN_KEY));
    URL url = new URL("http://localhost:" + wireMockRule.port() + "/log4j-test2.xml");
    StubMapping stubMapping = stubFor(get(urlPathEqualTo("/log4j-test2.xml"))
        .willReturn(aResponse()
            .withBodyFile(file)
            .withStatus(304)
            .withHeader("Last-Modified", formatter.format(now) + " GMT")
            .withHeader("Content-Type", XML)));
    final ConfigurationScheduler scheduler = new ConfigurationScheduler();
    scheduler.incrementScheduledItems();
    final WatchManager watchManager = new WatchManager(scheduler);
    watchManager.setIntervalSeconds(1);
    scheduler.start();
    watchManager.start();
    try {
        watchManager.watch(new Source(url.toURI(), previous.getTimeInMillis()), new HttpWatcher(configuration, null,
            listeners, previous.getTimeInMillis()));
        final String str = queue.poll(2, TimeUnit.SECONDS);
        assertNull("File changed.", str);
    } finally {
        removeStub(stubMapping);
        watchManager.stop();
        scheduler.stop();
    }
}
 
@Test
public void testDefaultLayout() throws Exception {
    // @formatter:off
    Assert.assertNotNull(RollingFileAppender.newBuilder()
            .setName(RollingFileAppenderLayoutTest.class.getName())
            .setConfiguration(new DefaultConfiguration())
            .setFileName("log.txt")
            .setFilePattern("FilePattern")
            .setPolicy(OnStartupTriggeringPolicy.createPolicy(1))
            .setCreateOnDemand(true) // no need to clutter up test folder with another file
            .build().getLayout());
    // @formatter:on
}
 
@Test
public void testPolicy() throws Exception {
    //System.setProperty("log4j2.debug", "true");
    //System.setProperty("log4j2.StatusLogger.level", "trace");
    final Configuration configuration = new DefaultConfiguration();
    final Path target = Paths.get(TARGET_FILE);
    target.toFile().getParentFile().mkdirs();
    final long timeStamp = System.currentTimeMillis() - (1000 * 60 * 60 * 24);
    final String expectedDate = formatter.format(timeStamp);
    final String rolledFileName = ROLLED_FILE_PREFIX + expectedDate + ROLLED_FILE_SUFFIX;
    final Path rolled = Paths.get(rolledFileName);
    final long copied;
    try (final InputStream is = new ByteArrayInputStream(TEST_DATA.getBytes("UTF-8"))) {
        copied = Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
    }
    final long size = Files.size(target);
    assertTrue(size > 0);
    assertEquals(copied, size);

    final FileTime fileTime = FileTime.fromMillis(timeStamp);
    final BasicFileAttributeView attrs = Files.getFileAttributeView(target, BasicFileAttributeView.class);
    attrs.setTimes(fileTime, fileTime, fileTime);
    final PatternLayout layout = PatternLayout.newBuilder().setPattern("%msg").setConfiguration(configuration)
            .build();
    final RolloverStrategy strategy = DefaultRolloverStrategy.newBuilder().setCompressionLevelStr("0")
            .setStopCustomActionsOnError(true).setConfig(configuration).build();
    final OnStartupTriggeringPolicy policy = OnStartupTriggeringPolicy.createPolicy(1);
    try (final RollingFileManager manager = RollingFileManager.getFileManager(TARGET_FILE, TARGET_PATTERN, true,
            false, policy, strategy, null, layout, 8192, true, false, null, null, null, configuration)) {
        manager.initialize();
        final String files = Arrays.toString(new File(TARGET_FOLDER).listFiles());
        assertTrue(target.toString() + ", files = " + files, Files.exists(target));
        assertEquals(target.toString(), 0, Files.size(target));
        assertTrue("Missing: " + rolled.toString() + ", files on disk = " + files, Files.exists(rolled));
        assertEquals(rolled.toString(), size, Files.size(rolled));
    }
}
 
源代码17 项目: logging-log4j2   文件: ScriptConditionTest.java
@Test
public void testSelectFilesToDelete() {
    final Configuration config = new DefaultConfiguration();
    config.initialize(); // creates the ScriptManager

    final Script script = new Script("test", "javascript", "pathList;"); // script that returns pathList
    final ScriptCondition condition = new ScriptCondition(script, config);
    final List<PathWithAttributes> pathList = new ArrayList<>();
    final Path base = Paths.get("baseDirectory");
    final List<PathWithAttributes> result = condition.selectFilesToDelete(base, pathList);
    assertSame(result, pathList);
}
 
源代码18 项目: logging-log4j2   文件: ScriptConditionTest.java
@Test
@Category(Scripts.Groovy.class)
public void testSelectFilesToDelete3() {
    final Configuration config = new DefaultConfiguration();
    config.initialize(); // creates the ScriptManager

    final List<PathWithAttributes> pathList = new ArrayList<>();
    pathList.add(new PathWithAttributes(Paths.get("/path/1/abc/a.txt"), new DummyFileAttributes()));
    pathList.add(new PathWithAttributes(Paths.get("/path/2/abc/bbb.txt"), new DummyFileAttributes()));
    pathList.add(new PathWithAttributes(Paths.get("/path/3/abc/c.txt"), new DummyFileAttributes()));

    final String scriptText = "" //
            + "import java.nio.file.*;" //
            + "def pattern = ~/(\\d*)[\\/\\\\]abc[\\/\\\\].*\\.txt/;" //
            + "assert pattern.getClass() == java.util.regex.Pattern;" //
            + "def copy = pathList.collect{it};"
            + "pathList.each { pathWithAttribs -> \n" //
            + "  def relative = basePath.relativize pathWithAttribs.path;" //
            + "  println 'relative path: ' + relative;" //
            + "  def str = relative.toString();"
            + "  def m = pattern.matcher(str);" //
            + "  if (m.find()) {" //
            + "    def index = m.group(1) as int;" //
            + "    println 'extracted index: ' + index;" //
            + "    def isOdd = (index % 2) == 1;"
            + "    println 'is odd: ' + isOdd;" //
            + "    if (isOdd) { copy.remove pathWithAttribs}"
            + "  }" //
            + "}" //
            + "println copy;"
            + "copy;";
    final Script script = new Script("test", "groovy", scriptText);
    final ScriptCondition condition = new ScriptCondition(script, config);
    final Path base = Paths.get("/path");
    final List<PathWithAttributes> result = condition.selectFilesToDelete(base, pathList);
    assertEquals(1, result.size());
    assertEquals(Paths.get("/path/2/abc/bbb.txt"), result.get(0).getPath());
}
 
源代码19 项目: logging-log4j2   文件: AsyncLoggerConfigTest.java
@Test
   public void testIncludeLocationDefaultsToFalse() {
   	final LoggerConfig rootLoggerConfig =
   			AsyncLoggerConfig.RootLogger.createLogger(
   					null, Level.INFO, null, new AppenderRef[0], null, new DefaultConfiguration(), null);
assertFalse("Include location should default to false for async loggers",
   			    rootLoggerConfig.isIncludeLocation());

   	final LoggerConfig loggerConfig =
   	        AsyncLoggerConfig.createLogger(
   	                false, Level.INFO, "com.foo.Bar", null, new AppenderRef[0], null, new DefaultConfiguration(),
   	        		null);
assertFalse("Include location should default to false for async loggers",
   			    loggerConfig.isIncludeLocation());
   }
 
源代码20 项目: summerframework   文件: CustomJsonLayout.java
public static CustomJsonLayout createDefaultLayout() {
    return new CustomJsonLayout(new DefaultConfiguration(), false, false, false, false, false, false,
        DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false);
}
 
源代码21 项目: core-ng-project   文件: ESLoggerConfigFactory.java
@Override
public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source) {
    return new DefaultConfiguration();
}
 
private static List<PatternFormatter> createFormatters() {
    final Configuration config = new DefaultConfiguration();
    final PatternParser parser = new PatternParser(config, "Converter", LogEventPatternConverter.class);
    return parser.parse("%d %5p [%t] %c{1} %X{transactionId} - %m%n", false, true);
}
 
@Test
public void testRolloverRetainsFileAttributes() throws Exception {

    // Short-circuit if host doesn't support file attributes.
    if (!FileUtils.isFilePosixAttributeViewSupported()) {
        return;
    }

    // Create the initial file.
    final File file = File.createTempFile("log4j2", "test");
    LockSupport.parkNanos(1000000); // 1 millisec

    // Set the initial file attributes.
    final String filePermissionsString = "rwxrwxrwx";
    final Set<PosixFilePermission> filePermissions =
            PosixFilePermissions.fromString(filePermissionsString);
    FileUtils.defineFilePosixAttributeView(file.toPath(), filePermissions, null, null);

    // Create the manager.
    final RolloverStrategy rolloverStrategy = DefaultRolloverStrategy
            .newBuilder()
            .setMax("7")
            .setMin("1")
            .setFileIndex("max")
            .setStopCustomActionsOnError(false)
            .setConfig(new DefaultConfiguration())
            .build();
    final RollingRandomAccessFileManager manager =
            RollingRandomAccessFileManager.getRollingRandomAccessFileManager(
                    file.getAbsolutePath(),
                    Strings.EMPTY,
                    true,
                    true,
                    RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE,
                    new SizeBasedTriggeringPolicy(Long.MAX_VALUE),
                    rolloverStrategy,
                    null,
                    null,
                    filePermissionsString,
                    null,
                    null,
                    null);
    assertNotNull(manager);
    manager.initialize();

    // Trigger a rollover.
    manager.rollover();

    // Verify the rolled over file attributes.
    final Set<PosixFilePermission> actualFilePermissions = Files
            .getFileAttributeView(
                    Paths.get(manager.getFileName()),
                    PosixFileAttributeView.class)
            .readAttributes()
            .permissions();
    assertEquals(filePermissions, actualFilePermissions);

}
 
源代码24 项目: logging-log4j2   文件: ScriptConditionTest.java
@Test(expected = NullPointerException.class)
public void testConstructorDisallowsNullScript() {
    new ScriptCondition(null, new DefaultConfiguration());
}
 
源代码25 项目: logging-log4j2   文件: ScriptConditionTest.java
@Test
public void testCreateConditionReturnsNullForNullScript() {
    assertNull(ScriptCondition.createCondition(null, new DefaultConfiguration()));
}
 
@Test
public void testCompositeLocationParameterWithEmptyUriListSetsDefaultConfiguration() {
    given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(",,,");

    this.initializerImpl.start();

    then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE), loggerContextCaptor.capture());
    assertNotNull("The context attribute should not be null.", loggerContextCaptor.getValue());

    assertThat(loggerContextCaptor.getValue().getConfiguration(), is(instanceOf(DefaultConfiguration.class)));

    this.initializerImpl.stop();
}
 
源代码27 项目: logging-log4j2   文件: YamlLayout.java
/**
 * Creates a YAML Layout using the default settings. Useful for testing.
 *
 * @return A YAML Layout.
 */
public static AbstractJacksonLayout createDefaultLayout() {
    return new YamlLayout(new DefaultConfiguration(), false, false, false, false, false, DEFAULT_HEADER,
            DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, false, null);
}
 
源代码28 项目: logging-log4j2   文件: JsonLayout.java
/**
 * Creates a JSON Layout using the default settings. Useful for testing.
 *
 * @return A JSON Layout.
 */
public static JsonLayout createDefaultLayout() {
    return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, false, null,
            DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, false, null, false);
}
 
 类所在包
 类方法
 同包方法